mirror of
https://github.com/vlang/v.git
synced 2025-08-03 17:57:59 -04:00
140 lines
3.7 KiB
V
140 lines
3.7 KiB
V
module asn1
|
|
|
|
import io
|
|
|
|
// Parser is ongoing ASN.1 parser.
|
|
// Its capables parsing ASN.1 element through availables methods.
|
|
pub struct Parser {
|
|
mut:
|
|
data []u8
|
|
}
|
|
|
|
// new creates a new Parser from bytes array in data.
|
|
pub fn Parser.new(data []u8) &Parser {
|
|
return &Parser{
|
|
data: data
|
|
}
|
|
}
|
|
|
|
// reset resets internal data of parser to empty buffer.
|
|
pub fn (mut p Parser) reset() {
|
|
p.data = unsafe { p.data[..0] }
|
|
}
|
|
|
|
// peek_tag lookups the tag from the parser without updates internal parser data.
|
|
pub fn (mut p Parser) peek_tag() !Tag {
|
|
tag, _ := Tag.from_bytes(p.data)!
|
|
return tag
|
|
}
|
|
|
|
// read_tag lookups the tag from the current parser and updates internal parser data.
|
|
pub fn (mut p Parser) read_tag() !Tag {
|
|
tag, rest := Tag.from_bytes(p.data)!
|
|
p.data = rest
|
|
return tag
|
|
}
|
|
|
|
// read_length read the Length from the current parser data.
|
|
pub fn (mut p Parser) read_length() !Length {
|
|
length, rest := Length.from_bytes(p.data)!
|
|
p.data = rest
|
|
return length
|
|
}
|
|
|
|
// read_bytes read length bytes from the current parser data.
|
|
pub fn (mut p Parser) read_bytes(length int) ![]u8 {
|
|
if length > p.data.len {
|
|
return error('Parser: too short data to read ${length} bytes')
|
|
}
|
|
result := p.data[0..length]
|
|
rest := if length == p.data.len { []u8{} } else { unsafe { p.data[length..] } }
|
|
p.data = rest
|
|
return result
|
|
}
|
|
|
|
// BUG: This is not supported with error:
|
|
// ```bash
|
|
// error: unknown function: asn1.Boolean__static__parse
|
|
// 57 | // Note: somes builtin have not this method.
|
|
// 58 | fn (mut p Parser) read_element[T]() !T {
|
|
// 59 | result := T.parse(mut p)!
|
|
// | ~~~~~~~~~~~~~~
|
|
// 60 | return result
|
|
// 61 | }
|
|
// vlib/x/encoding/asn1/parser.v:59:26: error: unexpected `!`,
|
|
// the function `T__static__parse` does not return a Result
|
|
// 57 | // Note: somes builtin have not this method.
|
|
// 58 | fn (mut p Parser) read_element[T]() !T {
|
|
// 59 | result := T.parse(mut p)!
|
|
// | ^
|
|
// 60 | return result
|
|
// 61 | }
|
|
// vlib/x/encoding/asn1/parser.v:59:9: error: assignment mismatch: 1 variable
|
|
// but `T.parse()` returns 0 values
|
|
// 57 | // Note: somes builtin have not this method.
|
|
// 58 | fn (mut p Parser) read_element[T]() !T {
|
|
// 59 | result := T.parse(mut p)!
|
|
// | ~~
|
|
// 60 | return result
|
|
// 61 | }
|
|
// ```
|
|
// read_element read an element T from the current parser.
|
|
// Note: somes builtin have not this method.
|
|
// fn (mut p Parser) read_element[T]() !T {
|
|
// result := T.parse(mut p)!
|
|
// return result
|
|
// }
|
|
|
|
// read_tlv read an Element from the parser data.
|
|
// Its return an Element, you should cast it to underlying data if you need.
|
|
pub fn (mut p Parser) read_tlv() !Element {
|
|
tag := p.read_tag()!
|
|
length := p.read_length()!
|
|
content := p.read_bytes(length)!
|
|
|
|
elem := parse_element(tag, content)!
|
|
return elem
|
|
}
|
|
|
|
// finish end this parser or error if not empty.
|
|
pub fn (mut p Parser) finish() ! {
|
|
if !p.is_empty() {
|
|
return error('not empty on finish')
|
|
}
|
|
}
|
|
|
|
// is_empty checks whether the parser has empty buffer data.
|
|
pub fn (mut p Parser) is_empty() bool {
|
|
return p.data.len == 0
|
|
}
|
|
|
|
// read_from read up to buf.len bytes from reader r, places them into buf and then appends
|
|
// to current Parser data.
|
|
fn (mut p Parser) read_from(mut r io.Reader, mut buf []u8) !int {
|
|
n := r.read(mut buf)!
|
|
p.data << buf
|
|
|
|
return n
|
|
}
|
|
|
|
fn parse_single[T](data []u8) !T {
|
|
mut p := Parser.new(data)!
|
|
out := p.read_element[T]()!
|
|
return out
|
|
}
|
|
|
|
fn parse[T](data []u8, callback fn (mut p Parser) !T) !T {
|
|
mut p := Parser.new(data)
|
|
result := callback(mut p)!
|
|
p.finish()!
|
|
return result
|
|
}
|
|
|
|
/*
|
|
fn strip_tlv(data []u8) !(Element, []u8) {
|
|
mut p := Parser.new(data)
|
|
tlv := p.read_element[Asn1Element]()!
|
|
return tlv, p.data
|
|
}
|
|
*/
|