diff --git a/CHANGES.md b/CHANGES.md index 7b2e1e33..d89a0472 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,10 @@ ### Removed +- Removed support for Tuple and Variant in JSON. It was a non-standard + extension that was rarely used, so this simplifies the Yojson types and the + parser more standard-conforming (#105, #158 @Leonidas-from-XIV) + ### Security ## 2.2.0 diff --git a/lib/common.ml b/lib/common.ml index df1b7d87..1ab59135 100644 --- a/lib/common.ml +++ b/lib/common.ml @@ -6,7 +6,6 @@ let json_error s = raise (Json_error s) exception End_of_array exception End_of_object -exception End_of_tuple exception End_of_input type lexer_state = { diff --git a/lib/common.mli b/lib/common.mli index 1f484e73..8e6aa7a2 100644 --- a/lib/common.mli +++ b/lib/common.mli @@ -36,7 +36,6 @@ val init_lexer : exception End_of_array exception End_of_object -exception End_of_tuple exception End_of_input (* end undocumented section *) diff --git a/lib/monomorphic.ml b/lib/monomorphic.ml index 121fc3a3..912323b4 100644 --- a/lib/monomorphic.ml +++ b/lib/monomorphic.ml @@ -67,34 +67,6 @@ let rec pp fmt = true) false xs); Format.fprintf fmt "@,]@]"; Format.fprintf fmt "@])" -#ifdef TUPLE - | `Tuple tup -> - Format.fprintf fmt "`Tuple (@["; - Format.fprintf fmt "@[<2>["; - ignore (List.fold_left - (fun sep e -> - if sep then - Format.fprintf fmt ";@ "; - pp fmt e; - true) false tup); - Format.fprintf fmt "@,]@]"; - Format.fprintf fmt "@])" -#endif -#ifdef VARIANT - | `Variant (name, value) -> - Format.fprintf fmt "`Variant (@["; - Format.fprintf fmt "(@["; - Format.fprintf fmt "%S" name; - Format.fprintf fmt ",@ "; - (match value with - | None -> Format.pp_print_string fmt "None" - | Some x -> - Format.pp_print_string fmt "(Some "; - pp fmt x; - Format.pp_print_string fmt ")"); - Format.fprintf fmt "@])"; - Format.fprintf fmt "@])" -#endif let show x = Format.asprintf "%a" pp x @@ -133,23 +105,10 @@ let rec equal a b = | exception Invalid_argument _ -> (* the lists were of different lengths, thus unequal *) false) -#ifdef TUPLE - | `Tuple xs, `Tuple ys -#endif | `List xs, `List ys -> (match List.for_all2 equal xs ys with | result -> result | exception Invalid_argument _ -> (* the lists were of different lengths, thus unequal *) false) -#ifdef VARIANT - | `Variant (name, value), `Variant (name', value') -> - (match name = name' with - | false -> false - | true -> - match value, value' with - | None, None -> true - | Some x, Some y -> equal x y - | _ -> false) -#endif | _ -> false diff --git a/lib/prettyprint.ml b/lib/prettyprint.ml index 2b896525..317d0aac 100644 --- a/lib/prettyprint.ml +++ b/lib/prettyprint.ml @@ -115,43 +115,6 @@ let rec format ~inside_box std (out:Format.formatter) (x:t) : unit = if not inside_box then Format.fprintf out "@["; Format.fprintf out "{@;<1 0>%a@;<1 -2>}" (pp_list "," (format_field std)) l; if not inside_box then Format.fprintf out "@]"; -#ifdef TUPLE - | `Tuple l -> - if std then - format ~inside_box std out (`List l) - else - if l = [] then - Format.pp_print_string out "()" - else ( - if not inside_box then Format.fprintf out "@["; - Format.fprintf out "(@,%a@;<0 -2>)" (pp_list "," (format ~inside_box:false std)) l; - if not inside_box then Format.fprintf out "@]"; - ) -#endif -#ifdef VARIANT - | `Variant (s, None) -> - if std then -#ifdef STRING - let representation = `String s in -#elif defined STRINGLIT - let representation = `Stringlit s in -#endif - format ~inside_box std out representation - else - Format.fprintf out "<%s>" (json_string_of_string s) - - | `Variant (s, Some x) -> - if std then -#ifdef STRING - let representation = `String s in -#elif defined STRINGLIT - let representation = `Stringlit s in -#endif - format ~inside_box std out (`List [ representation; x ]) - else - let op = json_string_of_string s in - Format.fprintf out "<@[%s: %a@]>" op (format ~inside_box:true std) x -#endif and format_field std out (name, x) = Format.fprintf out "@[%s: %a@]" (json_string_of_string name) (format ~inside_box:true std) x diff --git a/lib/read.mli b/lib/read.mli index 6963aa2a..f1ad8203 100644 --- a/lib/read.mli +++ b/lib/read.mli @@ -135,19 +135,10 @@ val finish_string : lexer_state -> Lexing.lexbuf -> string val read_string : lexer_state -> Lexing.lexbuf -> string val read_ident : lexer_state -> Lexing.lexbuf -> string -val map_string : - lexer_state -> (string -> int -> int -> 'a) -> Lexing.lexbuf -> 'a -(* equivalent to finish_string *) - val map_ident : lexer_state -> (string -> int -> int -> 'a) -> Lexing.lexbuf -> 'a (* equivalent to read_ident *) -type variant_kind = [ `Edgy_bracket | `Square_bracket | `Double_quote ] - -val start_any_variant : lexer_state -> Lexing.lexbuf -> variant_kind -val finish_variant : lexer_state -> Lexing.lexbuf -> t option -val finish_skip_variant : lexer_state -> Lexing.lexbuf -> unit val read_lt : lexer_state -> Lexing.lexbuf -> unit val read_gt : lexer_state -> Lexing.lexbuf -> unit val read_comma : lexer_state -> Lexing.lexbuf -> unit @@ -195,20 +186,8 @@ val read_array : Lexing.lexbuf -> 'a array -val read_tuple : - (int -> 'a -> lexer_state -> Lexing.lexbuf -> 'a) -> - 'a -> - lexer_state -> - Lexing.lexbuf -> - 'a - -val start_any_tuple : lexer_state -> Lexing.lexbuf -> bool val read_lpar : lexer_state -> Lexing.lexbuf -> unit val read_rpar : lexer_state -> Lexing.lexbuf -> unit -val read_tuple_end : Lexing.lexbuf -> unit -val read_tuple_end2 : lexer_state -> bool -> Lexing.lexbuf -> unit -val read_tuple_sep : lexer_state -> Lexing.lexbuf -> unit -val read_tuple_sep2 : lexer_state -> bool -> Lexing.lexbuf -> unit val read_lbr : lexer_state -> Lexing.lexbuf -> unit val read_rbr : lexer_state -> Lexing.lexbuf -> unit diff --git a/lib/read.mll b/lib/read.mll index 63f01178..e08b1243 100644 --- a/lib/read.mll +++ b/lib/read.mll @@ -146,8 +146,6 @@ let map_lexeme f (lexbuf : Lexing.lexbuf) = let len = lexbuf.lex_curr_pos - lexbuf.lex_start_pos in f (Bytes.sub_string lexbuf.lex_buffer lexbuf.lex_start_pos len) 0 len - - type variant_kind = [ `Edgy_bracket | `Square_bracket | `Double_quote ] } let space = [' ' '\t' '\r']+ @@ -250,38 +248,6 @@ rule read_json v = parse `List (List.rev !acc) } - | '(' { - #ifdef TUPLE - let acc = ref [] in - try - read_space v lexbuf; - read_tuple_end lexbuf; - acc := read_json v lexbuf :: !acc; - while true do - read_space v lexbuf; - read_tuple_sep v lexbuf; - read_space v lexbuf; - acc := read_json v lexbuf :: !acc; - done; - assert false - with Common.End_of_tuple -> - `Tuple (List.rev !acc) - #else - long_error "Invalid token" v lexbuf - #endif - } - - | '<' { - #ifdef VARIANT - read_space v lexbuf; - let cons = read_ident v lexbuf in - read_space v lexbuf; - `Variant (cons, finish_variant v lexbuf) - #else - long_error "Invalid token" v lexbuf - #endif - } - | "//"[^'\n']* { read_json v lexbuf } | "/*" { finish_comment v lexbuf; read_json v lexbuf } | "\n" { newline v lexbuf; read_json v lexbuf } @@ -356,15 +322,6 @@ and finish_stringlit v = parse | _ { long_error "Invalid string literal" v lexbuf } | eof { custom_error "Unexpected end of input" v lexbuf } -and finish_variant v = parse - ':' { let x = read_json v lexbuf in - read_space v lexbuf; - read_gt v lexbuf; - Some x } - | '>' { None } - | _ { long_error "Expected ':' or '>' but found" v lexbuf } - | eof { custom_error "Unexpected end of input" v lexbuf } - and read_lt v = parse '<' { () } | _ { long_error "Expected '<' but found" v lexbuf } @@ -380,14 +337,6 @@ and read_comma v = parse | _ { long_error "Expected ',' but found" v lexbuf } | eof { custom_error "Unexpected end of input" v lexbuf } -and start_any_variant v = parse - '<' { `Edgy_bracket } - | '"' { Buffer.clear v.buf; - `Double_quote } - | '[' { `Square_bracket } - | _ { long_error "Expected '<', '\"' or '[' but found" v lexbuf } - | eof { custom_error "Unexpected end of input" v lexbuf } - and finish_comment v = parse | "*/" { () } | eof { long_error "Unterminated comment" v lexbuf } @@ -592,68 +541,6 @@ and read_array_sep v = parse | _ { long_error "Expected ',' or ']' but found" v lexbuf } | eof { custom_error "Unexpected end of input" v lexbuf } - -and read_tuple read_cell init_acc v = parse - '(' { - #ifdef TUPLE - let pos = ref 0 in - let acc = ref init_acc in - try - read_space v lexbuf; - read_tuple_end lexbuf; - acc := read_cell !pos !acc v lexbuf; - incr pos; - while true do - read_space v lexbuf; - read_tuple_sep v lexbuf; - read_space v lexbuf; - acc := read_cell !pos !acc v lexbuf; - incr pos; - done; - assert false - with Common.End_of_tuple -> - !acc - #else - long_error "Invalid token" v lexbuf - #endif - } - | _ { long_error "Expected ')' but found" v lexbuf } - | eof { custom_error "Unexpected end of input" v lexbuf } - -and read_tuple_end = parse - ')' { raise Common.End_of_tuple } - | "" { () } - -and read_tuple_end2 v std = parse - ')' { if std then - long_error "Expected ')' or '' but found" v lexbuf - else - raise Common.End_of_tuple } - | ']' { if std then - raise Common.End_of_tuple - else - long_error "Expected ']' or '' but found" v lexbuf } - | "" { () } - -and read_tuple_sep v = parse - ',' { () } - | ')' { raise Common.End_of_tuple } - | _ { long_error "Expected ',' or ')' but found" v lexbuf } - | eof { custom_error "Unexpected end of input" v lexbuf } - -and read_tuple_sep2 v std = parse - ',' { () } - | ')' { if std then - long_error "Expected ',' or ']' but found" v lexbuf - else - raise Common.End_of_tuple } - | ']' { if std then - raise Common.End_of_tuple - else - long_error "Expected ',' or ')' but found" v lexbuf } - | _ { long_error "Expected ',' or ')' but found" v lexbuf } - | eof { custom_error "Unexpected end of input" v lexbuf } - (* Read a JSON object, reading the keys using a custom parser *) and read_abstract_fields read_key read_field init_acc v = parse '{' { let acc = ref init_acc in @@ -702,12 +589,6 @@ and read_colon v = parse | _ { long_error "Expected ':' but found" v lexbuf } | eof { custom_error "Unexpected end of input" v lexbuf } -and start_any_tuple v = parse - '(' { false } - | '[' { true } - | _ { long_error "Expected '(' or '[' but found" v lexbuf } - | eof { custom_error "Unexpected end of input" v lexbuf } - and read_lpar v = parse '(' { () } | _ { long_error "Expected '(' but found" v lexbuf } @@ -780,37 +661,6 @@ and skip_json v = parse () } - | '(' { - #ifdef TUPLE - try - read_space v lexbuf; - read_tuple_end lexbuf; - skip_json v lexbuf; - while true do - read_space v lexbuf; - read_tuple_sep v lexbuf; - read_space v lexbuf; - skip_json v lexbuf; - done; - assert false - with Common.End_of_tuple -> - () - #else - long_error "Invalid token" v lexbuf - #endif - } - - | '<' { - #ifdef VARIANT - read_space v lexbuf; - skip_ident v lexbuf; - read_space v lexbuf; - finish_skip_variant v lexbuf - #else - long_error "Invalid token" v lexbuf - #endif - } - | "//"[^'\n']* { skip_json v lexbuf } | "/*" { finish_comment v lexbuf; skip_json v lexbuf } | "\n" { newline v lexbuf; skip_json v lexbuf } @@ -826,14 +676,6 @@ and finish_skip_stringlit v = parse | _ { long_error "Invalid string literal" v lexbuf } | eof { custom_error "Unexpected end of input" v lexbuf } -and finish_skip_variant v = parse - ':' { skip_json v lexbuf; - read_space v lexbuf; - read_gt v lexbuf } - | '>' { () } - | _ { long_error "Expected ':' or '>' but found" v lexbuf } - | eof { custom_error "Unexpected end of input" v lexbuf } - and skip_ident v = parse '"' { finish_skip_stringlit v lexbuf } | ident { () } @@ -894,39 +736,6 @@ and buffer_json v = parse () } - | '(' { - #ifdef TUPLE - try - Buffer.add_char v.buf '('; - buffer_space v lexbuf; - buffer_tuple_end v lexbuf; - buffer_json v lexbuf; - while true do - buffer_space v lexbuf; - buffer_tuple_sep v lexbuf; - buffer_space v lexbuf; - buffer_json v lexbuf; - done; - assert false - with Common.End_of_tuple -> - () - #else - long_error "Invalid token" v lexbuf - #endif - } - - | '<' { - #ifdef VARIANT - Buffer.add_char v.buf '<'; - buffer_space v lexbuf; - buffer_ident v lexbuf; - buffer_space v lexbuf; - finish_buffer_variant v lexbuf - #else - long_error "Invalid token" v lexbuf - #endif - } - | "//"[^'\n']* { add_lexeme v.buf lexbuf; buffer_json v lexbuf } | "/*" { Buffer.add_string v.buf "/*"; finish_buffer_comment v lexbuf; @@ -948,15 +757,6 @@ and finish_buffer_stringlit v = parse | _ { long_error "Invalid string literal" v lexbuf } | eof { custom_error "Unexpected end of input" v lexbuf } -and finish_buffer_variant v = parse - ':' { Buffer.add_char v.buf ':'; - buffer_json v lexbuf; - buffer_space v lexbuf; - buffer_gt v lexbuf } - | '>' { Buffer.add_char v.buf '>' } - | _ { long_error "Expected ':' or '>' but found" v lexbuf } - | eof { custom_error "Unexpected end of input" v lexbuf } - and buffer_ident v = parse '"' { finish_buffer_stringlit v lexbuf } | ident { add_lexeme v.buf lexbuf } @@ -1003,18 +803,6 @@ and buffer_array_sep v = parse | _ { long_error "Expected ',' or ']' but found" v lexbuf } | eof { custom_error "Unexpected end of input" v lexbuf } -and buffer_tuple_end v = parse - ')' { - Buffer.add_char v.buf ')'; - raise Common.End_of_tuple } - | "" { () } - -and buffer_tuple_sep v = parse - ',' { Buffer.add_char v.buf ',' } - | ')' { Buffer.add_char v.buf ')'; raise Common.End_of_tuple } - | _ { long_error "Expected ',' or ')' but found" v lexbuf } - | eof { custom_error "Unexpected end of input" v lexbuf } - and buffer_colon v = parse ':' { Buffer.add_char v.buf ':' } | _ { long_error "Expected ':' but found" v lexbuf } diff --git a/lib/safe_to_basic.ml b/lib/safe_to_basic.ml index dabcfefd..7ba45d88 100644 --- a/lib/safe_to_basic.ml +++ b/lib/safe_to_basic.ml @@ -1,8 +1,6 @@ let rec to_basic : t -> Basic.t = function | (`Null | `Bool _ | `Int _ | `Float _ | `String _) as x -> x | `Intlit s -> `String s - | `List l | `Tuple l -> `List (List.rev (List.rev_map to_basic l)) + | `List l -> `List (List.rev (List.rev_map to_basic l)) | `Assoc l -> `Assoc (List.rev (List.rev_map (fun (k, v) -> (k, to_basic v)) l)) - | `Variant (k, None) -> `String k - | `Variant (k, Some v) -> `List [ `String k; to_basic v ] diff --git a/lib/type.ml b/lib/type.ml index ff8e05a5..b8505318 100644 --- a/lib/type.ml +++ b/lib/type.ml @@ -24,12 +24,6 @@ type t = #endif | `Assoc of (string * t) list | `List of t list -#ifdef TUPLE - | `Tuple of t list -#endif -#ifdef VARIANT - | `Variant of (string * t option) -#endif ] (** All possible cases defined in Yojson: @@ -47,10 +41,6 @@ All possible cases defined in Yojson: - `Stringlit of string: JSON string literal including the double quotes. - `Assoc of (string * json) list: JSON object. - `List of json list: JSON array. -- `Tuple of json list: Tuple (non-standard extension of JSON). - Syntax: [("abc", 123)]. -- `Variant of (string * json option): Variant (non-standard extension of JSON). - Syntax: [<"Foo">] or [<"Bar":123>]. *) (* diff --git a/lib/write.ml b/lib/write.ml index 73770804..6f7f8f24 100644 --- a/lib/write.ml +++ b/lib/write.ml @@ -244,12 +244,6 @@ let rec write_json ob (x : t) = #endif | `Assoc l -> write_assoc ob l | `List l -> write_list ob l -#ifdef TUPLE - | `Tuple l -> write_tuple ob l -#endif -#ifdef VARIANT - | `Variant (s, o) -> write_variant ob s o -#endif and write_assoc ob l = let f_elt ob (s, x) = @@ -266,26 +260,6 @@ and write_list ob l = iter2 write_json f_sep ob l; Buffer.add_char ob ']' -#ifdef TUPLE -and write_tuple ob l = - Buffer.add_char ob '('; - iter2 write_json f_sep ob l; - Buffer.add_char ob ')' -#endif - -#ifdef VARIANT -and write_variant ob s o = - Buffer.add_char ob '<'; - write_string ob s; - (match o with - None -> () - | Some x -> - Buffer.add_char ob ':'; - write_json ob x - ); - Buffer.add_char ob '>' -#endif - let write_t = write_json let rec write_std_json ob (x : t) = @@ -312,12 +286,6 @@ let rec write_std_json ob (x : t) = #endif | `Assoc l -> write_std_assoc ob l | `List l -> write_std_list ob l -#ifdef TUPLE - | `Tuple l -> write_std_tuple ob l -#endif -#ifdef VARIANT - | `Variant (s, o) -> write_std_variant ob s o -#endif and write_std_assoc ob l = let f_elt ob (s, x) = @@ -334,24 +302,6 @@ and write_std_list ob l = iter2 write_std_json f_sep ob l; Buffer.add_char ob ']' -and write_std_tuple ob l = - Buffer.add_char ob '['; - iter2 write_std_json f_sep ob l; - Buffer.add_char ob ']' - -#ifdef VARIANT -and write_std_variant ob s o = - match o with - None -> write_string ob s - | Some x -> - Buffer.add_char ob '['; - write_string ob s; - Buffer.add_char ob ','; - write_std_json ob x; - Buffer.add_char ob ']' -#endif - - let to_buffer ?(suf = "") ?(std = false) ob x = if std then write_std_json ob x @@ -449,15 +399,4 @@ let rec sort = function `Assoc (List.stable_sort (fun (a, _) (b, _) -> String.compare a b) l) | `List l -> `List (List.rev (List.rev_map sort l)) -#ifdef TUPLE - | `Tuple l -> - `Tuple (List.rev (List.rev_map sort l)) -#endif -#ifdef VARIANT - | `Variant (k, Some v) as x -> - let v' = sort v in - if v == v' then x - else - `Variant (k, Some v') -#endif | x -> x diff --git a/lib/write.mli b/lib/write.mli index bf3dd23b..84e04db9 100644 --- a/lib/write.mli +++ b/lib/write.mli @@ -143,14 +143,6 @@ val write_stringlit : Buffer.t -> string -> unit val write_assoc : Buffer.t -> (string * t) list -> unit val write_list : Buffer.t -> t list -> unit -#ifdef TUPLE -val write_tuple : Buffer.t -> t list -> unit -val write_std_tuple : Buffer.t -> t list -> unit -#endif -#ifdef VARIANT -val write_variant : Buffer.t -> string -> t option -> unit -val write_std_variant : Buffer.t -> string -> t option -> unit -#endif val write_json : Buffer.t -> t -> unit val write_std_json : Buffer.t -> t -> unit diff --git a/test/pretty/sample.json b/test/pretty/sample.json index 2c384bc8..1caf8eda 100644 --- a/test/pretty/sample.json +++ b/test/pretty/sample.json @@ -1,7 +1,5 @@ { "abc": [ 1, 2, -3 ], - cd: (1.2, "zz"), - ef : [ , , ], aaaaoooaoaooooooooaoaoaoooaoa: { "big int": 123456789012345678901837292020484756564574 }, diff --git a/test/pretty/test.expected.json b/test/pretty/test.expected.json index 0c571fea..f20771a8 100644 --- a/test/pretty/test.expected.json +++ b/test/pretty/test.expected.json @@ -1,7 +1,5 @@ { "abc": [ 1, 2, -3 ], - "cd": (1.2, "zz"), - "ef": [ <"Int": 123>, <"Null">, <"Test": "abcdefghijklmnopqrstuvwxyz"> ], "aaaaoooaoaooooooooaoaoaoooaoa": { "big int": 123456789012345678901837292020484756564574 }, diff --git a/test/test_read.ml b/test/test_read.ml index 3979a0f4..19291eac 100644 --- a/test/test_read.ml +++ b/test/test_read.ml @@ -78,7 +78,7 @@ let unquoted_from_string () = __LOC__ Fixtures.unquoted_value (Yojson.Safe.from_string Fixtures.unquoted_json) -let map_ident_and_string () = +let map_ident () = let lexbuf = Lexing.from_string {|{foo:"hello"}|} in let lexer_state = Yojson.init_lexer () in @@ -93,17 +93,13 @@ let map_ident_and_string () = let skip_over f = f lexer_state lexbuf in let map_f mapper f = mapper lexer_state f lexbuf in let map_ident = map_f Yojson.Safe.map_ident in - let map_string = map_f Yojson.Safe.map_string in skip_over Yojson.Safe.read_lcurl; map_ident (ident_expected "foo"); skip_over Yojson.Safe.read_colon; - let variant = skip_over Yojson.Safe.start_any_variant in - Alcotest.(check Testable.variant_kind) - "String starts with double quote" `Double_quote variant; - - map_string (ident_expected "hello"); + let key = skip_over Yojson.Safe.read_string in + Alcotest.(check string) "String is as expected" "hello" key; Alcotest.check_raises "Reading } raises End_of_object" Yojson.End_of_object (fun () -> Yojson.Safe.read_object_end lexbuf) @@ -131,5 +127,5 @@ let single_json = ("from_string_fail_escaped_char", `Quick, from_string_fail_escaped_char); ("from_file", `Quick, from_file); ("unquoted_from_string", `Quick, unquoted_from_string); - ("map_ident/map_string", `Quick, map_ident_and_string); + ("map_ident", `Quick, map_ident); ] diff --git a/test/testable.ml b/test/testable.ml index 5729a9e7..58dbac08 100644 --- a/test/testable.ml +++ b/test/testable.ml @@ -1,15 +1 @@ let yojson = Alcotest.testable Yojson.Safe.pp Yojson.Safe.equal - -let variant_kind_pp fmt = function - | `Edgy_bracket -> Format.fprintf fmt "`Edgy_bracket" - | `Square_bracket -> Format.fprintf fmt "`Square_bracket" - | `Double_quote -> Format.fprintf fmt "`Double_quote" - -let variant_kind_equal a b = - match (a, b) with - | `Edgy_bracket, `Edgy_bracket -> true - | `Square_bracket, `Square_bracket -> true - | `Double_quote, `Double_quote -> true - | _ -> false - -let variant_kind = Alcotest.testable variant_kind_pp variant_kind_equal diff --git a/test/testable.mli b/test/testable.mli index ec9dc127..364708c2 100644 --- a/test/testable.mli +++ b/test/testable.mli @@ -1,2 +1 @@ val yojson : Yojson.Safe.t Alcotest.testable -val variant_kind : Yojson.Safe.variant_kind Alcotest.testable