| // 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 |
| } |