mirror of
https://github.com/vlang/v.git
synced 2025-09-09 07:15:50 -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.
|
||||
pub fn (el Element) length() !int {
|
||||
payload := el.payload()!
|
||||
return payload.len
|
||||
return el.payload()!.len
|
||||
}
|
||||
|
||||
// UTILITY HELPER FOR ELEMENT
|
||||
@ -225,8 +224,7 @@ fn (el Element) equal_payload(other Element) bool {
|
||||
}
|
||||
|
||||
fn Element.decode(src []u8) !(Element, int) {
|
||||
el, pos := Element.decode_with_rule(src, 0, .der)!
|
||||
return el, pos
|
||||
return Element.decode_with_rule(src, 0, .der)!
|
||||
}
|
||||
|
||||
// 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')
|
||||
}
|
||||
// TODO: default
|
||||
el := tlv.unwrap_with_field_options(fo)!
|
||||
return el
|
||||
return tlv.unwrap_with_field_options(fo)!
|
||||
}
|
||||
|
||||
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]
|
||||
// ```
|
||||
pub fn encode_with_options(el Element, opt string) ![]u8 {
|
||||
return el.encode_with_options(opt)!
|
||||
}
|
||||
|
||||
// `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
|
||||
// treated as without option when empty
|
||||
if opt.len == 0 {
|
||||
return encode_with_rule(el, .der)!
|
||||
}
|
||||
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.
|
||||
fn (el Element) encode_with_field_options(fo FieldOptions) ![]u8 {
|
||||
// `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 {
|
||||
// validates options again this element.
|
||||
el.validate_options(fo)!
|
||||
|
||||
@ -81,33 +72,7 @@ fn (el Element) encode_with_field_options(fo FieldOptions) ![]u8 {
|
||||
return new_el.encode()!
|
||||
}
|
||||
// otherwise, just serializing it
|
||||
out := 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
|
||||
return encode_with_rule(new_el, .der)!
|
||||
}
|
||||
|
||||
// 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
|
||||
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) {
|
||||
cls, num := parse_tag_marker(item)!
|
||||
tag_ctr += 1
|
||||
|
@ -46,19 +46,6 @@ pub fn RawElement.new(tag Tag, content []u8) !RawElement {
|
||||
return RawElement{
|
||||
tag: tag
|
||||
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
|
||||
}
|
||||
|
||||
// force_set_mode forces to change tagged mode of RawElement into mode.
|
||||
// It will change how the element was interpreted.
|
||||
pub fn (mut r RawElement) force_set_mode(mode TaggedMode) ! {
|
||||
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) ! {
|
||||
// set_mode sets the RawElement tagged mode, in explicit or implicit mode. If the mode has been set,
|
||||
// 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) set_mode(mode TaggedMode, force bool) ! {
|
||||
if r.tag.class == .universal {
|
||||
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
|
||||
}
|
||||
|
||||
// set_inner_tag sets the inner tag of the RawElement into inner_tag.
|
||||
// If its already set, it would return error.
|
||||
// Use `force_set_inner_tag` instead to force it.
|
||||
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) ! {
|
||||
// set_inner_tag sets the inner tag of the RawElement into inner_tag value. If it has been already set,
|
||||
// it would be an error until you setting force flag into true value to replace the old one.
|
||||
pub fn (mut r RawElement) set_inner_tag(inner_tag Tag, force bool) ! {
|
||||
// not needed in universal class
|
||||
if r.tag.class == .universal {
|
||||
return error('No need it on universal class')
|
||||
}
|
||||
// we need mode first
|
||||
mode := r.mode or { return error('unmeet_requirement, set the mode first') }
|
||||
|
||||
// when its explicit, compares the provided tag with tag from the inner element.
|
||||
mode := r.mode or { return error('You dont set any mode') }
|
||||
// when its in explicit mode, compares the provided tag with tag from the inner element.
|
||||
if mode == .explicit {
|
||||
if !r.tag.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.
|
||||
pub fn (mut r RawElement) force_set_default_value(value Element) ! {
|
||||
r.set_default_value_with_flag(value, true)!
|
||||
}
|
||||
|
||||
// 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.
|
||||
fn (mut r RawElement) set_default_value(value Element, force bool) ! {
|
||||
// default value of this element should have an equal tag.
|
||||
if !value.tag().equal(r.tag) {
|
||||
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.
|
||||
pub fn (r RawElement) inner_tag() !Tag {
|
||||
inner_tag := r.inner_tag or { return error(' r.inner_tag is not set') }
|
||||
|
||||
return inner_tag
|
||||
pub fn (r RawElement) inner_tag() ?Tag {
|
||||
return r.inner_tag
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return error('inner element from universal class is not availables')
|
||||
}
|
||||
mode := r.mode 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 !r.tag.constructed {
|
||||
return error('tag should be constructed when in explicit')
|
||||
@ -302,11 +254,8 @@ fn ContextElement.decode_raw(bytes []u8) !(ContextElement, int) {
|
||||
next := content_pos + length
|
||||
// Raw ContextElement, you should provide mode and inner tag.
|
||||
ctx := ContextElement{
|
||||
tag: tag
|
||||
content: content
|
||||
inner_tag: none
|
||||
mode: none
|
||||
default_value: none
|
||||
tag: tag
|
||||
content: content
|
||||
}
|
||||
return ctx, next
|
||||
}
|
||||
|
@ -32,13 +32,6 @@ mut:
|
||||
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.
|
||||
pub fn Sequence.new() !Sequence {
|
||||
return Sequence.new_with_size(default_sequence_size)!
|
||||
@ -240,13 +233,6 @@ mut:
|
||||
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]
|
||||
pub fn SequenceOf.new[T]() SequenceOf[T] {
|
||||
return SequenceOf[T]{}
|
||||
|
@ -23,13 +23,6 @@ mut:
|
||||
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.
|
||||
pub fn Set.new() !Set {
|
||||
return Set.new_with_size(default_set_size)!
|
||||
@ -247,13 +240,6 @@ pub fn SetOf.new[T]() !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.
|
||||
pub fn SetOf.from_list[T](els []T) !SetOf[T] {
|
||||
$if T !is Element {
|
||||
|
@ -59,8 +59,8 @@ Example ::= SEQUENCE {
|
||||
assert els[1] is Integer
|
||||
mut els2 := els[2] as ContextElement
|
||||
|
||||
els2.set_mode(.explicit)!
|
||||
els2.set_inner_tag(default_oid_tag)!
|
||||
els2.set_mode(.explicit, true)!
|
||||
els2.set_inner_tag(default_oid_tag, true)!
|
||||
|
||||
out.clear()
|
||||
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
|
||||
utime := t.local_to_utc()
|
||||
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 {
|
||||
u := t.local_to_utc()
|
||||
s := u.custom_format(default_genztime_format)
|
||||
|
@ -116,6 +116,8 @@ fn test_create_generalizedtime_from_std_time() ! {
|
||||
gtc := GeneralizedTime.from_time(now)!
|
||||
|
||||
assert gtb.value == gtc.value
|
||||
assert gtb.value == '20241113174550Z'
|
||||
assert gtc.value == '20241113174550Z'
|
||||
|
||||
tt := gtc.into_utctime()!
|
||||
assert now == tt
|
||||
|
Loading…
x
Reference in New Issue
Block a user