blob: 7ec6084ef1d3aa9aa06a451b49f2927d51e067b5 [file] [log] [blame]
// Copyright 2020 The Wuffs Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub status "#bad input"
pri status "#internal error: inconsistent I/O"
pub struct decoder? implements base.token_decoder(
end_of_data : base.bool,
util : base.utility,
)(
)
pub func decoder.set_quirk_enabled!(quirk: base.u32, enabled: base.bool) {
}
pub func decoder.workbuf_len() base.range_ii_u64 {
return this.util.empty_range_ii_u64()
}
pub func decoder.decode_tokens?(dst: base.token_writer, src: base.io_reader, workbuf: slice base.u8) {
var depth : base.u32[..= 1024]
var token_length : base.u32[..= 9]
var c : base.u8
if this.end_of_data {
return base."@end of data"
}
while.outer true {
while.goto_parsed_a_leaf_value true {{
if args.dst.available() <= 0 {
yield? base."$short write"
continue.outer
}
if args.src.available() <= 0 {
if args.src.is_closed() {
return "#bad input"
}
yield? base."$short read"
continue.outer
}
c = args.src.peek_u8()
if (0x18 <= (c & 0x1F)) and ((c & 0x1F) <= 0x1B) {
token_length = 1 + ((1 as base.u32) << (c & 0x03))
if args.src.available() < (token_length as base.u64) {
if args.src.is_closed() {
return "#bad input"
}
yield? base."$short read"
continue.outer
}
args.src.skip_u32?(n: token_length)
} else {
args.src.skip_u32_fast!(actual: 1, worst_case: 1)
}
if c < 0x20 {
c &= 0x1F
if c < 0x18 {
args.dst.write_simple_token_fast!(
value_major: 0,
value_minor: (base.TOKEN__VBC__INLINE_INTEGER << 21) |
(c as base.u32),
continued: 0,
length: 1)
break.goto_parsed_a_leaf_value
} else if c < 0x1C {
args.dst.write_simple_token_fast!(
value_major: 0,
value_minor: (base.TOKEN__VBC__NUMBER << 21) |
base.TOKEN__VBD__NUMBER__CONTENT_INTEGER_UNSIGNED |
base.TOKEN__VBD__NUMBER__FORMAT_BINARY_BIG_ENDIAN |
base.TOKEN__VBD__NUMBER__FORMAT_IGNORE_FIRST_BYTE,
continued: 0,
length: 1 + ((1 as base.u32) << (c - 0x18)))
break.goto_parsed_a_leaf_value
}
}
if args.src.can_undo_byte() {
args.src.undo_byte!()
return "#bad input"
}
return "#internal error: inconsistent I/O"
}} endwhile.goto_parsed_a_leaf_value
// We've just parsed a leaf (non-container) value: literal (null,
// false, true), number or string.
if depth == 0 {
break.outer
}
} endwhile.outer
this.end_of_data = true
}