diff --git a/json/internal_types.mbt b/json/internal_types.mbt index 66fcfb8df..3d6e6ab81 100644 --- a/json/internal_types.mbt +++ b/json/internal_types.mbt @@ -15,13 +15,16 @@ ///| priv struct ParseContext { mut offset : Int - input : String + input : StringView end_offset : Int mut remaining_available_depth : Int } ///| -fn ParseContext::make(input : String, max_nesting_depth : Int) -> ParseContext { +fn ParseContext::make( + input : StringView, + max_nesting_depth : Int, +) -> ParseContext { { offset: 0, input, diff --git a/json/lex_main.mbt b/json/lex_main.mbt index 5d5e0361f..1b79d5065 100644 --- a/json/lex_main.mbt +++ b/json/lex_main.mbt @@ -63,12 +63,12 @@ fn ParseContext::lex_value( match ctx.read_char() { Some('0') => { let (n, repr) = ctx.lex_zero(start=ctx.offset - 2) - return Number(n, repr) + return Number(n, repr.map(_.to_string())) } Some(c2) => { if c2 is ('1'..='9') { let (n, repr) = ctx.lex_decimal_integer(start=ctx.offset - 2) - return Number(n, repr) + return Number(n, repr.map(_.to_string())) } ctx.invalid_char(shift=-1) } @@ -76,11 +76,11 @@ fn ParseContext::lex_value( } Some('0') => { let (n, repr) = ctx.lex_zero(start=ctx.offset - 1) - return Number(n, repr) + return Number(n, repr.map(_.to_string())) } Some('1'..='9') => { let (n, repr) = ctx.lex_decimal_integer(start=ctx.offset - 1) - return Number(n, repr) + return Number(n, repr.map(_.to_string())) } Some('"') => { let s = ctx.lex_string() diff --git a/json/lex_number.mbt b/json/lex_number.mbt index 11f55af75..440f3de6b 100644 --- a/json/lex_number.mbt +++ b/json/lex_number.mbt @@ -16,7 +16,7 @@ fn ParseContext::lex_decimal_integer( ctx : ParseContext, start~ : Int, -) -> (Double, String?) raise ParseError { +) -> (Double, StringView?) raise ParseError { for { match ctx.read_char() { Some('.') => return ctx.lex_decimal_point(start~) @@ -37,7 +37,7 @@ fn ParseContext::lex_decimal_integer( fn ParseContext::lex_decimal_point( ctx : ParseContext, start~ : Int, -) -> (Double, String?) raise ParseError { +) -> (Double, StringView?) raise ParseError { match ctx.read_char() { Some(c) => if c >= '0' && c <= '9' { @@ -53,7 +53,7 @@ fn ParseContext::lex_decimal_point( fn ParseContext::lex_decimal_fraction( ctx : ParseContext, start~ : Int, -) -> (Double, String?) raise ParseError { +) -> (Double, StringView?) raise ParseError { for { match ctx.read_char() { Some('e' | 'E') => return ctx.lex_decimal_exponent(start~) @@ -73,7 +73,7 @@ fn ParseContext::lex_decimal_fraction( fn ParseContext::lex_decimal_exponent( ctx : ParseContext, start~ : Int, -) -> (Double, String?) raise ParseError { +) -> (Double, StringView?) raise ParseError { match ctx.read_char() { Some('+') | Some('-') => return ctx.lex_decimal_exponent_sign(start~) Some(c) => { @@ -91,7 +91,7 @@ fn ParseContext::lex_decimal_exponent( fn ParseContext::lex_decimal_exponent_sign( ctx : ParseContext, start~ : Int, -) -> (Double, String?) raise ParseError { +) -> (Double, StringView?) raise ParseError { match ctx.read_char() { Some(c) => { if c >= '0' && c <= '9' { @@ -108,7 +108,7 @@ fn ParseContext::lex_decimal_exponent_sign( fn ParseContext::lex_decimal_exponent_integer( ctx : ParseContext, start~ : Int, -) -> (Double, String?) { +) -> (Double, StringView?) { for { match ctx.read_char() { Some(c) => { @@ -127,7 +127,7 @@ fn ParseContext::lex_decimal_exponent_integer( fn ParseContext::lex_zero( ctx : ParseContext, start~ : Int, -) -> (Double, String?) raise ParseError { +) -> (Double, StringView?) raise ParseError { match ctx.read_char() { Some('.') => ctx.lex_decimal_point(start~) Some('e' | 'E') => ctx.lex_decimal_exponent(start~) @@ -148,8 +148,8 @@ fn ParseContext::lex_number_end( ctx : ParseContext, start : Int, end : Int, -) -> (Double, String?) { - let s = ctx.input.unsafe_substring(start~, end~) +) -> (Double, StringView?) { + let s = ctx.input.view(start_offset=start, end_offset=end) if !s.contains(".") && !s.contains("e") && !s.contains("E") { // If the string does not contain a decimal point or exponent, it is likely an integer // We can try to parse it as an integer first diff --git a/json/lex_string.mbt b/json/lex_string.mbt index a8f6504f0..d27431333 100644 --- a/json/lex_string.mbt +++ b/json/lex_string.mbt @@ -18,7 +18,11 @@ fn ParseContext::lex_string(ctx : ParseContext) -> String raise ParseError { let mut start = ctx.offset fn flush(end : Int) { if start > 0 && end > start { - buf.write_substring(ctx.input, start, end - start) + buf.write_substring( + ctx.input.data(), + ctx.input.start_offset() + start, + end - start, + ) } } diff --git a/json/parse.mbt b/json/parse.mbt index 0d5cb95a2..72504d2da 100644 --- a/json/parse.mbt +++ b/json/parse.mbt @@ -13,7 +13,7 @@ // limitations under the License. ///| -pub fn valid(input : String) -> Bool { +pub fn valid(input : StringView) -> Bool { try { parse(input) |> ignore true @@ -25,7 +25,7 @@ pub fn valid(input : String) -> Bool { ///| /// Parse a JSON input string into a Json value, with an optional maximum nesting depth (default is 1024) pub fn parse( - input : String, + input : StringView, max_nesting_depth? : Int = 1024, ) -> Json raise ParseError { let ctx = ParseContext::make(input, max_nesting_depth) diff --git a/json/pkg.generated.mbti b/json/pkg.generated.mbti index 9091f6d9e..fae4d62c4 100644 --- a/json/pkg.generated.mbti +++ b/json/pkg.generated.mbti @@ -7,9 +7,9 @@ fn[T : FromJson] from_json(Json, path? : JsonPath) -> T raise JsonDecodeError #callsite(autofill(args_loc, loc)) fn inspect(&ToJson, content? : Json, loc~ : SourceLoc, args_loc~ : ArgsLoc) -> Unit raise InspectError -fn parse(String, max_nesting_depth? : Int) -> Json raise ParseError +fn parse(StringView, max_nesting_depth? : Int) -> Json raise ParseError -fn valid(String) -> Bool +fn valid(StringView) -> Bool // Errors pub(all) suberror JsonDecodeError (JsonPath, String) diff --git a/json/utils.mbt b/json/utils.mbt index 732bf3b9b..153d20059 100644 --- a/json/utils.mbt +++ b/json/utils.mbt @@ -13,7 +13,7 @@ // limitations under the License. ///| -fn offset_to_position(input : String, offset : Int) -> Position { +fn offset_to_position(input : StringView, offset : Int) -> Position { let mut line = 1 let mut column = 0 for i in 0..