mirror of
https://github.com/vlang/v.git
synced 2025-08-03 17:57:59 -04:00
80 lines
2.5 KiB
V
80 lines
2.5 KiB
V
module asn1
|
|
|
|
// ASN.1 OPTIONAL Element.
|
|
//
|
|
// note: At the abstract ASN.1 level the absence of a DEFAULT value in an encoding is the same as its being present.
|
|
// Contrast this with OPTIONAL, where a value being present in the encoding is semantically distinct from its being absent.
|
|
// In some encoding rules (like BER/PER) it is at the whim of the sender whether a DEFAULT value is encoded or not
|
|
// (except for primitive type values in PER which are required by the PER standard to be absent in the encoding),
|
|
// while with others (like DER) the DEFAULT value is NEVER encoded. For all encoding rules,
|
|
// if the component that has a DEFAULT value is not encoded the receiving application must behave as though the DEFAULT value had been encoded.
|
|
pub struct Optional {
|
|
// underlying element marked as an optional
|
|
elem Element
|
|
mut:
|
|
// presence of this flag negates optionality of this elemeent.
|
|
// set to true when its should present, if not sure, just set to to false
|
|
present bool
|
|
}
|
|
|
|
// new creates and marked element as an Optional element.
|
|
pub fn Optional.new(el Element, with_present bool) !Optional {
|
|
if el is Optional {
|
|
return error('recursive optional is not allowed')
|
|
}
|
|
return Optional{
|
|
elem: el
|
|
present: with_present
|
|
}
|
|
}
|
|
|
|
// set_present_bit sets this Optional element with flag in present.
|
|
pub fn (mut opt Optional) set_present_bit(present bool) {
|
|
opt.present = present
|
|
}
|
|
|
|
// tag returns the tag of Optional element.
|
|
pub fn (opt Optional) tag() Tag {
|
|
return opt.elem.tag()
|
|
}
|
|
|
|
// payload the payload of Optional element.
|
|
pub fn (opt Optional) payload() ![]u8 {
|
|
return opt.elem.payload()!
|
|
}
|
|
|
|
// encode serializes this Optional element into bytes array.
|
|
pub fn (opt Optional) encode() ![]u8 {
|
|
return opt.encode_with_rule(.der)!
|
|
}
|
|
|
|
fn (opt Optional) encode_with_rule(rule EncodingRule) ![]u8 {
|
|
if opt.present {
|
|
// elem := opt.into_element()!
|
|
return encode_with_rule(opt, .der)!
|
|
}
|
|
// not present
|
|
return []u8{}
|
|
}
|
|
|
|
// into_element turns this optional into Element.
|
|
pub fn (opt Optional) into_element() !Element {
|
|
return parse_element(opt.tag(), opt.payload()!)!
|
|
}
|
|
|
|
// into_object tries to turns this optional into real underlying object T.
|
|
// Its return object T on success or error on fails.
|
|
pub fn (opt Optional) into_object[T]() !T {
|
|
$if T !is Element {
|
|
return error('T is not element')
|
|
}
|
|
$if T is Optional {
|
|
return error('T is optional')
|
|
}
|
|
elem := opt.into_element()!
|
|
if elem is Optional {
|
|
return error('elem is also optional')
|
|
}
|
|
return elem.into_object[T]()!
|
|
}
|