mirror of
https://github.com/vlang/v.git
synced 2025-09-10 07:47:20 -04:00
x.encoding.asn1: cleanup code, improve performance (#22968)
This commit is contained in:
parent
904bccb564
commit
94905820e6
@ -67,8 +67,7 @@ pub fn (el Element) into_object[T]() !T {
|
|||||||
|
|
||||||
// length tells the payload length of this element.
|
// length tells the payload length of this element.
|
||||||
pub fn (el Element) length() !int {
|
pub fn (el Element) length() !int {
|
||||||
payload := el.payload()!
|
return el.payload()!.len
|
||||||
return payload.len
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UTILITY HELPER FOR ELEMENT
|
// UTILITY HELPER FOR ELEMENT
|
||||||
@ -225,8 +224,7 @@ fn (el Element) equal_payload(other Element) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn Element.decode(src []u8) !(Element, int) {
|
fn Element.decode(src []u8) !(Element, int) {
|
||||||
el, pos := Element.decode_with_rule(src, 0, .der)!
|
return Element.decode_with_rule(src, 0, .der)!
|
||||||
return el, pos
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// decode deserializes back bytes in src from offet `loc` into Element.
|
// decode deserializes back bytes in src from offet `loc` into Element.
|
||||||
|
@ -99,8 +99,7 @@ pub fn decode_with_field_options(bytes []u8, fo FieldOptions) !Element {
|
|||||||
return error('Get different tag number')
|
return error('Get different tag number')
|
||||||
}
|
}
|
||||||
// TODO: default
|
// TODO: default
|
||||||
el := tlv.unwrap_with_field_options(fo)!
|
return tlv.unwrap_with_field_options(fo)!
|
||||||
return el
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_optional(bytes []u8, expected_tag Tag) !Element {
|
fn decode_optional(bytes []u8, expected_tag Tag) !Element {
|
||||||
|
@ -39,25 +39,16 @@ pub fn encode(el Element) ![]u8 {
|
|||||||
// assert explicit_out == [u8(0xA5), 0x04, 0x0C, 0x02, 0x68, 0x69]
|
// assert explicit_out == [u8(0xA5), 0x04, 0x0C, 0x02, 0x68, 0x69]
|
||||||
// ```
|
// ```
|
||||||
pub fn encode_with_options(el Element, opt string) ![]u8 {
|
pub fn encode_with_options(el Element, opt string) ![]u8 {
|
||||||
return el.encode_with_options(opt)!
|
// treated as without option when empty
|
||||||
}
|
|
||||||
|
|
||||||
// `encode_with_field_options` serializes this element into bytes array with options defined in fo.
|
|
||||||
pub fn encode_with_field_options(el Element, fo FieldOptions) ![]u8 {
|
|
||||||
return el.encode_with_field_options(fo)!
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (el Element) encode_with_options(opt string) ![]u8 {
|
|
||||||
// treated as without option when nil
|
|
||||||
if opt.len == 0 {
|
if opt.len == 0 {
|
||||||
return encode_with_rule(el, .der)!
|
return encode_with_rule(el, .der)!
|
||||||
}
|
}
|
||||||
fo := FieldOptions.from_string(opt)!
|
fo := FieldOptions.from_string(opt)!
|
||||||
return el.encode_with_field_options(fo)!
|
return encode_with_field_options(el, fo)!
|
||||||
}
|
}
|
||||||
|
|
||||||
// encode_with_field_options serializes element into bytes arrays with supplied FieldOptions.
|
// `encode_with_field_options` serializes this element into bytes array with options defined in fo.
|
||||||
fn (el Element) encode_with_field_options(fo FieldOptions) ![]u8 {
|
pub fn encode_with_field_options(el Element, fo FieldOptions) ![]u8 {
|
||||||
// validates options again this element.
|
// validates options again this element.
|
||||||
el.validate_options(fo)!
|
el.validate_options(fo)!
|
||||||
|
|
||||||
@ -81,33 +72,7 @@ fn (el Element) encode_with_field_options(fo FieldOptions) ![]u8 {
|
|||||||
return new_el.encode()!
|
return new_el.encode()!
|
||||||
}
|
}
|
||||||
// otherwise, just serializing it
|
// otherwise, just serializing it
|
||||||
out := encode_with_rule(new_el, .der)!
|
return encode_with_rule(new_el, .der)!
|
||||||
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// encode_with_rule encodes element into bytes array with rule.
|
|
||||||
fn encode_with_rule(el Element, rule EncodingRule) ![]u8 {
|
|
||||||
if rule != .der && rule != .ber {
|
|
||||||
return error('Element: unsupported rule')
|
|
||||||
}
|
|
||||||
mut dst := []u8{}
|
|
||||||
|
|
||||||
// when this element is Optional without presence flag, by default would
|
|
||||||
// serialize this element into empty bytes otherwise, would serialize underlying element.
|
|
||||||
if el is Optional {
|
|
||||||
return el.encode()!
|
|
||||||
}
|
|
||||||
// otherwise, just serializes as normal
|
|
||||||
el.tag().encode_with_rule(mut dst, rule)!
|
|
||||||
// calculates the length of element, and serialize this length
|
|
||||||
payload := el.payload()!
|
|
||||||
length := Length.new(payload.len)!
|
|
||||||
length.encode_with_rule(mut dst, rule)!
|
|
||||||
// append the element payload to destination
|
|
||||||
dst << payload
|
|
||||||
|
|
||||||
return dst
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper for wrapping element
|
// Helper for wrapping element
|
||||||
@ -201,3 +166,27 @@ fn wrap(el Element, cls TagClass, number int, mode TaggedMode) !Element {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// encode_with_rule encodes element into bytes array with rule.
|
||||||
|
fn encode_with_rule(el Element, rule EncodingRule) ![]u8 {
|
||||||
|
if rule != .der && rule != .ber {
|
||||||
|
return error('Element: unsupported rule')
|
||||||
|
}
|
||||||
|
mut dst := []u8{}
|
||||||
|
|
||||||
|
// when this element is Optional without presence flag, by default would
|
||||||
|
// serialize this element into empty bytes otherwise, would serialize underlying element.
|
||||||
|
if el is Optional {
|
||||||
|
return el.encode()!
|
||||||
|
}
|
||||||
|
// otherwise, just serializes as normal
|
||||||
|
el.tag().encode_with_rule(mut dst, rule)!
|
||||||
|
// calculates the length of element, and serialize this length
|
||||||
|
payload := el.payload()!
|
||||||
|
length := Length.new(payload.len)!
|
||||||
|
length.encode_with_rule(mut dst, rule)!
|
||||||
|
// append the element payload to destination
|
||||||
|
dst << payload
|
||||||
|
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
@ -115,10 +115,6 @@ pub fn FieldOptions.from_attrs(attrs []string) !FieldOptions {
|
|||||||
|
|
||||||
// The item has space-trimmed
|
// The item has space-trimmed
|
||||||
for item in filtered {
|
for item in filtered {
|
||||||
if !is_tag_marker(item) && !is_optional_marker(item) && !is_default_marker(item)
|
|
||||||
&& !is_mode_marker(item) && !is_inner_tag_marker(item) {
|
|
||||||
return error('unsupported keyword')
|
|
||||||
}
|
|
||||||
if is_tag_marker(item) {
|
if is_tag_marker(item) {
|
||||||
cls, num := parse_tag_marker(item)!
|
cls, num := parse_tag_marker(item)!
|
||||||
tag_ctr += 1
|
tag_ctr += 1
|
||||||
|
@ -46,19 +46,6 @@ pub fn RawElement.new(tag Tag, content []u8) !RawElement {
|
|||||||
return RawElement{
|
return RawElement{
|
||||||
tag: tag
|
tag: tag
|
||||||
content: content
|
content: content
|
||||||
// Issues: without set this to `none`, when compiled with `-cstrict` options, its would bring
|
|
||||||
// into failed compiles error:
|
|
||||||
// ================= C compilation error (from clang): ==============
|
|
||||||
// error: incompatible pointer types passing '_option_x__encoding__asn1__Tag *'
|
|
||||||
// (aka 'struct _option_x__encoding__asn1__Tag *') to parameter of type '_option *'
|
|
||||||
// (aka 'struct _option *') [-Werror,-Wincompatible-pointer-types]
|
|
||||||
// cc: _option_none(&(x__encoding__asn1__Tag[])
|
|
||||||
// { ((x__encoding__asn1__Tag){.__v_class =
|
|
||||||
// x__encoding__asn1__TagClass__universal,.constructed = 0,.number = 0,})},
|
|
||||||
// &_t6, sizeof(x__encoding__asn1__Tag)); ```
|
|
||||||
inner_tag: none
|
|
||||||
mode: none
|
|
||||||
default_value: none
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,19 +80,9 @@ pub fn (r RawElement) payload() ![]u8 {
|
|||||||
return r.content
|
return r.content
|
||||||
}
|
}
|
||||||
|
|
||||||
// force_set_mode forces to change tagged mode of RawElement into mode.
|
// set_mode sets the RawElement tagged mode, in explicit or implicit mode. If the mode has been set,
|
||||||
// It will change how the element was interpreted.
|
// it would drop into error until you forces it by setting force flag into true value, ie, replaces the old one.
|
||||||
pub fn (mut r RawElement) force_set_mode(mode TaggedMode) ! {
|
pub fn (mut r RawElement) set_mode(mode TaggedMode, force bool) ! {
|
||||||
r.set_mode_with_flag(mode, true)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// set_mode sets the tagged mode of the RawElement into mode.
|
|
||||||
// If you want force it to use the mode, use `force_set_mode`.
|
|
||||||
pub fn (mut r RawElement) set_mode(mode TaggedMode) ! {
|
|
||||||
r.set_mode_with_flag(mode, false)!
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (mut r RawElement) set_mode_with_flag(mode TaggedMode, force bool) ! {
|
|
||||||
if r.tag.class == .universal {
|
if r.tag.class == .universal {
|
||||||
return error('No need it on universal class')
|
return error('No need it on universal class')
|
||||||
}
|
}
|
||||||
@ -120,28 +97,15 @@ fn (mut r RawElement) set_mode_with_flag(mode TaggedMode, force bool) ! {
|
|||||||
r.mode = mode
|
r.mode = mode
|
||||||
}
|
}
|
||||||
|
|
||||||
// set_inner_tag sets the inner tag of the RawElement into inner_tag.
|
// set_inner_tag sets the inner tag of the RawElement into inner_tag value. If it has been already set,
|
||||||
// If its already set, it would return error.
|
// it would be an error until you setting force flag into true value to replace the old one.
|
||||||
// Use `force_set_inner_tag` instead to force it.
|
pub fn (mut r RawElement) set_inner_tag(inner_tag Tag, force bool) ! {
|
||||||
pub fn (mut r RawElement) set_inner_tag(inner_tag Tag) ! {
|
|
||||||
r.set_inner_tag_with_flag(inner_tag, false)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// force_set_inner_tag forces to set the inner tag of the RawElement into inner_tag
|
|
||||||
// even its has been set previously.
|
|
||||||
pub fn (mut r RawElement) force_set_inner_tag(inner_tag Tag) ! {
|
|
||||||
r.set_inner_tag_with_flag(inner_tag, true)!
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (mut r RawElement) set_inner_tag_with_flag(inner_tag Tag, force bool) ! {
|
|
||||||
// not needed in universal class
|
// not needed in universal class
|
||||||
if r.tag.class == .universal {
|
if r.tag.class == .universal {
|
||||||
return error('No need it on universal class')
|
return error('No need it on universal class')
|
||||||
}
|
}
|
||||||
// we need mode first
|
mode := r.mode or { return error('You dont set any mode') }
|
||||||
mode := r.mode or { return error('unmeet_requirement, set the mode first') }
|
// when its in explicit mode, compares the provided tag with tag from the inner element.
|
||||||
|
|
||||||
// when its explicit, compares the provided tag with tag from the inner element.
|
|
||||||
if mode == .explicit {
|
if mode == .explicit {
|
||||||
if !r.tag.constructed {
|
if !r.tag.constructed {
|
||||||
return error('unmeet_requirement, explicit should be constructed')
|
return error('unmeet_requirement, explicit should be constructed')
|
||||||
@ -164,17 +128,8 @@ fn (mut r RawElement) set_inner_tag_with_flag(inner_tag Tag, force bool) ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// force_set_default_value forces set default value of this RawElement into value.
|
// force_set_default_value forces set default value of this RawElement into value.
|
||||||
pub fn (mut r RawElement) force_set_default_value(value Element) ! {
|
fn (mut r RawElement) set_default_value(value Element, force bool) ! {
|
||||||
r.set_default_value_with_flag(value, true)!
|
// default value of this element should have an equal tag.
|
||||||
}
|
|
||||||
|
|
||||||
// set_default_value sets the default value of this RawElement to some value.
|
|
||||||
pub fn (mut r RawElement) set_default_value(value Element) ! {
|
|
||||||
r.set_default_value_with_flag(value, false)!
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (mut r RawElement) set_default_value_with_flag(value Element, force bool) ! {
|
|
||||||
// default value of this element should have equal tag.
|
|
||||||
if !value.tag().equal(r.tag) {
|
if !value.tag().equal(r.tag) {
|
||||||
return error('You provides unequal tag for default value')
|
return error('You provides unequal tag for default value')
|
||||||
}
|
}
|
||||||
@ -189,10 +144,8 @@ fn (mut r RawElement) set_default_value_with_flag(value Element, force bool) ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// inner_tag returns the inner tag of the RawElement if it exists, or error on fails.
|
// inner_tag returns the inner tag of the RawElement if it exists, or error on fails.
|
||||||
pub fn (r RawElement) inner_tag() !Tag {
|
pub fn (r RawElement) inner_tag() ?Tag {
|
||||||
inner_tag := r.inner_tag or { return error(' r.inner_tag is not set') }
|
return r.inner_tag
|
||||||
|
|
||||||
return inner_tag
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// inner_element returns the inner element of the RawElement if its exists.
|
// inner_element returns the inner element of the RawElement if its exists.
|
||||||
@ -200,9 +153,8 @@ pub fn (r RawElement) inner_element() !Element {
|
|||||||
if r.tag.class == .universal {
|
if r.tag.class == .universal {
|
||||||
return error('inner element from universal class is not availables')
|
return error('inner element from universal class is not availables')
|
||||||
}
|
}
|
||||||
mode := r.mode or { return err }
|
|
||||||
inner_tag := r.inner_tag or { return err }
|
inner_tag := r.inner_tag or { return err }
|
||||||
|
mode := r.mode or { return error('You dont set any mode') }
|
||||||
if mode == .explicit {
|
if mode == .explicit {
|
||||||
if !r.tag.constructed {
|
if !r.tag.constructed {
|
||||||
return error('tag should be constructed when in explicit')
|
return error('tag should be constructed when in explicit')
|
||||||
@ -304,9 +256,6 @@ fn ContextElement.decode_raw(bytes []u8) !(ContextElement, int) {
|
|||||||
ctx := ContextElement{
|
ctx := ContextElement{
|
||||||
tag: tag
|
tag: tag
|
||||||
content: content
|
content: content
|
||||||
inner_tag: none
|
|
||||||
mode: none
|
|
||||||
default_value: none
|
|
||||||
}
|
}
|
||||||
return ctx, next
|
return ctx, next
|
||||||
}
|
}
|
||||||
|
@ -32,13 +32,6 @@ mut:
|
|||||||
fields []Element
|
fields []Element
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (s Sequence) str() string {
|
|
||||||
if s.fields.len == 0 {
|
|
||||||
return 'SEQUENCE: <empty>'
|
|
||||||
}
|
|
||||||
return 'SEQUENCE: ${s.fields.len} elements.'
|
|
||||||
}
|
|
||||||
|
|
||||||
// new creates new Sequence with default size.
|
// new creates new Sequence with default size.
|
||||||
pub fn Sequence.new() !Sequence {
|
pub fn Sequence.new() !Sequence {
|
||||||
return Sequence.new_with_size(default_sequence_size)!
|
return Sequence.new_with_size(default_sequence_size)!
|
||||||
@ -240,13 +233,6 @@ mut:
|
|||||||
fields []T
|
fields []T
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (s SequenceOf[T]) str() string {
|
|
||||||
if s.fields.len == 0 {
|
|
||||||
return 'SEQUENCE OF (<empty>)'
|
|
||||||
}
|
|
||||||
return 'SEQUENCE OF (${s.fields.len} ${typeof(s).name})'
|
|
||||||
}
|
|
||||||
|
|
||||||
// SequenceOf.new creates a new SequenceOf[T]
|
// SequenceOf.new creates a new SequenceOf[T]
|
||||||
pub fn SequenceOf.new[T]() SequenceOf[T] {
|
pub fn SequenceOf.new[T]() SequenceOf[T] {
|
||||||
return SequenceOf[T]{}
|
return SequenceOf[T]{}
|
||||||
|
@ -23,13 +23,6 @@ mut:
|
|||||||
fields []Element
|
fields []Element
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (s Set) str() string {
|
|
||||||
if s.fields.len == 0 {
|
|
||||||
return 'SET (<empty>)'
|
|
||||||
}
|
|
||||||
return 'SET (${s.fields.len} Elements)'
|
|
||||||
}
|
|
||||||
|
|
||||||
// creates a new Set with default size.
|
// creates a new Set with default size.
|
||||||
pub fn Set.new() !Set {
|
pub fn Set.new() !Set {
|
||||||
return Set.new_with_size(default_set_size)!
|
return Set.new_with_size(default_set_size)!
|
||||||
@ -247,13 +240,6 @@ pub fn SetOf.new[T]() !SetOf[T] {
|
|||||||
return SetOf[T]{}
|
return SetOf[T]{}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (s SetOf[T]) str() string {
|
|
||||||
if s.fields.len == 0 {
|
|
||||||
return 'SET OF (<empty>)'
|
|
||||||
}
|
|
||||||
return 'SET OF (${s.fields.len} ${typeof(s).name})'
|
|
||||||
}
|
|
||||||
|
|
||||||
// from_list creates new SetOf type T from arrays of T.
|
// from_list creates new SetOf type T from arrays of T.
|
||||||
pub fn SetOf.from_list[T](els []T) !SetOf[T] {
|
pub fn SetOf.from_list[T](els []T) !SetOf[T] {
|
||||||
$if T !is Element {
|
$if T !is Element {
|
||||||
|
@ -59,8 +59,8 @@ Example ::= SEQUENCE {
|
|||||||
assert els[1] is Integer
|
assert els[1] is Integer
|
||||||
mut els2 := els[2] as ContextElement
|
mut els2 := els[2] as ContextElement
|
||||||
|
|
||||||
els2.set_mode(.explicit)!
|
els2.set_mode(.explicit, true)!
|
||||||
els2.set_inner_tag(default_oid_tag)!
|
els2.set_inner_tag(default_oid_tag, true)!
|
||||||
|
|
||||||
out.clear()
|
out.clear()
|
||||||
out = encode(els2)!
|
out = encode(els2)!
|
||||||
|
@ -50,7 +50,8 @@ pub fn UtcTime.new(s string) !UtcTime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn UtcTime.from_time(t time.Time) !UtcTime {
|
// from_time creates a new UtcTime element from standard `time.Time` in UTC time format.
|
||||||
|
pub fn UtcTime.from_time(t time.Time) !UtcTime {
|
||||||
// changes into utc time
|
// changes into utc time
|
||||||
utime := t.local_to_utc()
|
utime := t.local_to_utc()
|
||||||
s := utime.custom_format(default_utctime_format) // 20241113060446+0
|
s := utime.custom_format(default_utctime_format) // 20241113060446+0
|
||||||
@ -226,7 +227,7 @@ pub fn GeneralizedTime.new(s string) !GeneralizedTime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// from_time creates GeneralizedTime element from tine.Time (as an UTC time).
|
// from_time creates GeneralizedTime element from standard `time.Time` (as an UTC time).
|
||||||
pub fn GeneralizedTime.from_time(t time.Time) !GeneralizedTime {
|
pub fn GeneralizedTime.from_time(t time.Time) !GeneralizedTime {
|
||||||
u := t.local_to_utc()
|
u := t.local_to_utc()
|
||||||
s := u.custom_format(default_genztime_format)
|
s := u.custom_format(default_genztime_format)
|
||||||
|
@ -116,6 +116,8 @@ fn test_create_generalizedtime_from_std_time() ! {
|
|||||||
gtc := GeneralizedTime.from_time(now)!
|
gtc := GeneralizedTime.from_time(now)!
|
||||||
|
|
||||||
assert gtb.value == gtc.value
|
assert gtb.value == gtc.value
|
||||||
|
assert gtb.value == '20241113174550Z'
|
||||||
|
assert gtc.value == '20241113174550Z'
|
||||||
|
|
||||||
tt := gtc.into_utctime()!
|
tt := gtc.into_utctime()!
|
||||||
assert now == tt
|
assert now == tt
|
||||||
|
Loading…
x
Reference in New Issue
Block a user