// // Copyright (c) 2021, Brian Frank and Andy Frank // Licensed under the Academic Free License version 3.0 // // History: // 05 Aug 2021 Matthew Giannini Creation // ** ** ASN.1 Tag ** final const class AsnTag { ////////////////////////////////////////////////////////////////////////// // Constructor ////////////////////////////////////////////////////////////////////////// ** Get a [builder]`AsnTagBuilder` for a universal tag with the given id. static AsnTagBuilder univ(Int id) { AsnTagBuilder().univ.id(id) } ** Get a [builder]`AsnTagBuilder` for a context tag with the given id static AsnTagBuilder context(Int id) { AsnTagBuilder().context.id(id) } ** Get a [builder]`AsnTagBuilder` for an application tag with the given id static AsnTagBuilder app(Int id) { AsnTagBuilder().app.id(id) } ** Get a [builder]`AsnTagBuilder` for a private tag with the given id static AsnTagBuilder priv(Int id) { AsnTagBuilder().priv.id(id) } new make(AsnTagClass cls, Int id, AsnTagMode mode) { this.cls = cls this.id = id this.mode = mode } ////////////////////////////////////////////////////////////////////////// // Identity ////////////////////////////////////////////////////////////////////////// ** The [tag class]`AsnTagClass` const AsnTagClass cls ** The tag id const Int id ** The [tag mode]`AsnTagMode` const AsnTagMode mode @NoDoc AsnTag toCls(AsnTagClass newCls) { AsnTag(newCls, id, mode) } @NoDoc AsnTag toId(Int newId) { AsnTag(cls, newId, mode) } ////////////////////////////////////////////////////////////////////////// // Universal Tags ////////////////////////////////////////////////////////////////////////// @NoDoc public static const AsnTag univAny := AsnTag.univ(-1).explicit public static const AsnTag univBool := AsnTag.univ(1).explicit public static const AsnTag univInt := AsnTag.univ(2).explicit public static const AsnTag univBits := AsnTag.univ(3).explicit public static const AsnTag univOcts := AsnTag.univ(4).explicit public static const AsnTag univNull := AsnTag.univ(5).explicit public static const AsnTag univOid := AsnTag.univ(6).explicit // public static const AsnTag univObjDesc := AsnTag.explicit(TagClass.univ, 7) // public static const AsnTag univExt := AsnTag.explicit(TagClass.univ, 8) public static const AsnTag univReal := AsnTag.univ(9).explicit public static const AsnTag univEnum := AsnTag.univ(10).explicit // public static const AsnTag univPdv := AsnTag.explicit(TagClass.univ, 11) public static const AsnTag univUtf8 := AsnTag.univ(12).explicit // public static const AsnTag univRelOid := AsnTag.explicit(TagClass.univ, 13) // 14 - reserved // 15 - reserved public static const AsnTag univSeq := AsnTag.univ(16).explicit public static const AsnTag univSet := AsnTag.univ(17).explicit // public static const AsnTag univNumStr := AsnTag.explicit(TagClass.univ, 18) public static const AsnTag univPrintStr := AsnTag.univ(19).explicit // public static const AsnTag univTeleStr := AsnTag.explicit(TagClass.univ, 20) // public static const AsnTag univVidStr := AsnTag.explicit(TagClass.univ, 21) public static const AsnTag univIa5Str := AsnTag.univ(22).explicit public static const AsnTag univUtcTime := AsnTag.univ(23).explicit public static const AsnTag univGenTime := AsnTag.univ(24).explicit public static const AsnTag univGraphStr := AsnTag.univ(25).explicit public static const AsnTag univVisStr := AsnTag.univ(26).explicit ////////////////////////////////////////////////////////////////////////// // Obj ////////////////////////////////////////////////////////////////////////// override Int hash() { res := 31 + cls.hash res = (31 * res) + id // res = (31 * res) + mode.hash return res } ** Tag equality is based only the [class]`AsnTagClass` and 'id'. The ** [mode]`AsnTagMode` is ignored for eqality purposes. override Bool equals(Obj? obj) { if (this === obj) return true that := obj as AsnTag if (that == null) return false if (this.cls !== that.cls) return false if (this.id != that.id) return false // if (this.mode != that.mode) return false return true } Bool strictEquals(Obj? obj) { if (this === obj) return true that := obj as AsnTag if (that == null) return false if (this.cls !== that.cls) return false if (this.id != that.id) return false if (this.mode != that.mode) return false return true } override Str toStr() { "<$cls, $id, $mode>" } } ************************************************************************** ** TagClass ************************************************************************** ** ** The tag class for an `AsnTag` ** enum class AsnTagClass { univ(0x00), app(0x40), context(0x80), priv(0xc0) private new make(Int mask) { this.mask = mask } const Int mask; ** Is this the 'UNIVERSAL' class Bool isUniv() { this === AsnTagClass.univ } ** Is this the 'APPLICATION' class Bool isApp() { this === AsnTagClass.app } ** Is this the 'CONTEXT' class Bool isContext() { this === AsnTagClass.context } ** Is this the 'PRIVATE' class Bool isPriv() { this === AsnTagClass.priv } } ************************************************************************** ** AsnTagMode ************************************************************************** ** ** The tag mode for a `AsnTag` ** enum class AsnTagMode { explicit, implicit } ************************************************************************** ** AsnTagBuilder ************************************************************************** ** ** Utility to build an `AsnTag`. ** ** See: ** - `AsnTag.univ` ** - `AsnTag.context` ** - `AsnTag.app` ** - `AsnTag.priv` ** class AsnTagBuilder { ** Create an unconfigured builder new make() { } private AsnTagClass? cls private Int? identifier ** Set the tag class to universal This univ() { this.cls = AsnTagClass.univ; return this } ** Set the tag class to context This context() { this.cls = AsnTagClass.context; return this } ** Set the tag class to application This app() { this.cls = AsnTagClass.app; return this } ** Set the tag class to private This priv() { this.cls = AsnTagClass.priv; return this } ** Set the tag identifier This id(Int id) { this.identifier = id; return this } ** Build the tag with explicit mode AsnTag explicit() { check return AsnTag(cls, identifier, AsnTagMode.explicit) } ** Build the tag with implicit mode AsnTag implicit() { check return AsnTag(cls, identifier, AsnTagMode.implicit) } private Void check() { if (cls == null) throw AsnErr("Tag class is not configured") if (identifier == null) throw AsnErr("Tag identifier not configured") } }