Skip to content

Commit a6a768d

Browse files
authored
Merge pull request #233 from emillon/ignore-underscore-fields
Ignore underscore fields
2 parents 9437574 + 7dfd205 commit a6a768d

File tree

3 files changed

+144
-117
lines changed

3 files changed

+144
-117
lines changed

ppx/ppx_cstruct.ml

Lines changed: 123 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ type field = {
4545
off: int;
4646
}
4747

48+
let field_is_ignored f =
49+
String.get f.field 0 = '_'
50+
4851
type t = {
4952
name: string;
5053
fields: field list;
@@ -150,154 +153,138 @@ let op_name s op =
150153

151154
let op_pvar s op = Ast.pvar (op_name s op)
152155
let op_evar s op = Ast.evar (op_name s op)
153-
let op_val_typ loc s op ty =
154-
Sig.value (Val.mk (Loc.mkloc (op_name s op) loc) ty)
155156

156-
let output_get _loc s f =
157-
let m = mode_mod _loc s.endian in
157+
let get_expr loc s f =
158+
let m = mode_mod loc s.endian in
158159
let num x = Ast.int x in
159160
match f.ty with
160161
|Buffer (_, _) ->
161162
let len = width_of_field f in
162-
[%str
163-
let [%p op_pvar s (Op_get f)] =
164-
fun src -> Cstruct.sub src [%e num f.off] [%e num len]
165-
166-
let[@ocaml.warning "-32"] [%p op_pvar s (Op_copy f)] =
167-
fun src -> Cstruct.copy src [%e num f.off] [%e num len]
163+
[%expr
164+
fun src -> Cstruct.sub src [%e num f.off] [%e num len]
168165
]
169166
|Prim prim ->
170-
[%str
171-
let [%p op_pvar s (Op_get f)] = fun v ->
167+
[%expr
168+
fun v ->
172169
[%e match prim with
173170
|Char -> [%expr Cstruct.get_char v [%e num f.off]]
174171
|UInt8 -> [%expr Cstruct.get_uint8 v [%e num f.off]]
175172
|UInt16 -> [%expr [%e m "get_uint16"] v [%e num f.off]]
176173
|UInt32 -> [%expr [%e m "get_uint32"] v [%e num f.off]]
177174
|UInt64 -> [%expr [%e m "get_uint64"] v [%e num f.off]]]]
178175

179-
let output_get loc s f =
180-
(output_get loc s f) [@metaloc loc]
181-
182176
let type_of_int_field = function
183177
|Char -> [%type: char]
184178
|UInt8 -> [%type: Cstruct.uint8]
185179
|UInt16 -> [%type: Cstruct.uint16]
186180
|UInt32 -> [%type: Cstruct.uint32]
187181
|UInt64 -> [%type: Cstruct.uint64]
188182

189-
let type_of_int_field _loc x =
190-
type_of_int_field x [@metaloc loc]
191-
192-
let output_get_sig loc s f =
193-
match f.ty with
194-
|Buffer (_,_) ->
195-
[
196-
op_val_typ loc s (Op_get f) [%type: Cstruct.t -> Cstruct.t];
197-
op_val_typ loc s (Op_copy f) [%type: Cstruct.t -> string]
198-
]
199-
|Prim prim ->
200-
let retf = type_of_int_field loc prim in
201-
[
202-
op_val_typ loc s (Op_get f) [%type: Cstruct.t -> [%t retf]]
203-
]
204-
205-
let output_get_sig _loc s f =
206-
output_get_sig _loc s f [@metaloc _loc]
207-
208-
let output_set _loc s f =
209-
let m = mode_mod _loc s.endian in
183+
let set_expr loc s f =
184+
let m = mode_mod loc s.endian in
210185
let num x = Ast.int x in
211186
match f.ty with
212187
|Buffer (_,_) ->
213188
let len = width_of_field f in
214-
[%str
215-
let[@ocaml.warning "-32"] [%p op_pvar s (Op_set f)] = fun src srcoff dst ->
216-
Cstruct.blit_from_string src srcoff dst [%e num f.off] [%e num len]
217-
218-
let[@ocaml.warning "-32"] [%p op_pvar s (Op_blit f)] = fun src srcoff dst ->
219-
Cstruct.blit src srcoff dst [%e num f.off] [%e num len]]
189+
[%expr
190+
fun src srcoff dst ->
191+
Cstruct.blit_from_string src srcoff dst [%e num f.off] [%e num len]]
220192
|Prim prim ->
221-
[%str
222-
let[@ocaml.warning "-32"] [%p op_pvar s (Op_set f)] = fun v x ->
193+
[%expr fun v x ->
223194
[%e match prim with
224195
|Char -> [%expr Cstruct.set_char v [%e num f.off] x]
225196
|UInt8 -> [%expr Cstruct.set_uint8 v [%e num f.off] x]
226197
|UInt16 -> [%expr [%e m "set_uint16"] v [%e num f.off] x]
227198
|UInt32 -> [%expr [%e m "set_uint32"] v [%e num f.off] x]
228199
|UInt64 -> [%expr [%e m "set_uint64"] v [%e num f.off] x]]]
229200

230-
let output_set _loc s f =
231-
output_set _loc s f [@metaloc _loc]
232-
233-
let output_set_sig loc s f =
201+
let type_of_set f =
234202
match f.ty with
235203
|Buffer (_,_) ->
236-
[
237-
op_val_typ loc s (Op_set f) [%type: string -> int -> Cstruct.t -> unit];
238-
op_val_typ loc s (Op_blit f) [%type: Cstruct.t -> int -> Cstruct.t -> unit]
239-
] [@metaloc loc]
204+
[%type: string -> int -> Cstruct.t -> unit]
240205
|Prim prim ->
241-
let retf = type_of_int_field loc prim in
242-
[
243-
op_val_typ loc s (Op_set f) [%type: Cstruct.t -> [%t retf] -> unit]
244-
] [@metaloc loc]
245-
246-
let output_sizeof _loc s =
247-
[%stri
248-
let [%p op_pvar s Op_sizeof] = [%e Ast.int s.len]] [@metaloc _loc]
249-
250-
let output_sizeof_sig loc s =
251-
op_val_typ loc s Op_sizeof [%type: int]
252-
253-
let output_hexdump _loc s =
254-
let hexdump =
255-
List.fold_left (fun a f ->
256-
let get_f = op_evar s (Op_get f) in
257-
[%expr
258-
[%e a]; Buffer.add_string _buf [%e Ast.str (" "^f.field^" = ")];
259-
[%e match f.ty with
260-
|Prim Char ->
261-
[%expr Printf.bprintf _buf "%c\n" ([%e get_f] v)]
262-
|Prim (UInt8|UInt16) ->
263-
[%expr Printf.bprintf _buf "0x%x\n" ([%e get_f] v)]
264-
|Prim UInt32 ->
265-
[%expr Printf.bprintf _buf "0x%lx\n" ([%e get_f] v)]
266-
|Prim UInt64 ->
267-
[%expr Printf.bprintf _buf "0x%Lx\n" ([%e get_f] v)]
268-
|Buffer (_,_) ->
269-
[%expr Printf.bprintf _buf "<buffer %s>"
270-
[%e Ast.str (field_to_string f)];
271-
Cstruct.hexdump_to_buffer _buf ([%e get_f] v)]
272-
]]
273-
) (Ast.unit ()) s.fields
274-
in
275-
[
276-
[%stri
277-
let [%p op_pvar s Op_hexdump_to_buffer] = fun _buf v ->
278-
[%e hexdump]];
279-
[%stri
280-
let[@ocaml.warning "-32"] [%p op_pvar s Op_hexdump] = fun v ->
281-
let _buf = Buffer.create 128 in
282-
Buffer.add_string _buf [%e Ast.str (s.name ^ " = {\n")];
283-
[%e op_evar s Op_hexdump_to_buffer] _buf v;
284-
print_endline (Buffer.contents _buf);
285-
print_endline "}"
286-
]
287-
] [@metaloc _loc]
288-
289-
let output_hexdump_sig loc s =
290-
[
291-
op_val_typ loc s Op_hexdump_to_buffer [%type: Buffer.t -> Cstruct.t -> unit];
292-
op_val_typ loc s Op_hexdump [%type: Cstruct.t -> unit];
206+
let retf = type_of_int_field prim in
207+
[%type: Cstruct.t -> [%t retf] -> unit]
208+
209+
let hexdump_expr s =
210+
[%expr fun v ->
211+
let buf = Buffer.create 128 in
212+
Buffer.add_string buf [%e Ast.str (s.name ^ " = {\n")];
213+
[%e op_evar s Op_hexdump_to_buffer] buf v;
214+
print_endline (Buffer.contents buf);
215+
print_endline "}"
293216
]
294217

295-
let output_struct_one_endian _loc s =
296-
(* Generate functions of the form {get/set}_<struct>_<field> *)
297-
let expr = List.fold_left (fun a f ->
298-
a @ output_get _loc s f @ output_set _loc s f
299-
) [output_sizeof _loc s] s.fields
300-
in expr @ output_hexdump _loc s
218+
let hexdump_to_buffer_expr s =
219+
let prim_format_string = function
220+
| Char -> [%expr "%c\n"]
221+
| UInt8 | UInt16 -> [%expr "0x%x\n"]
222+
| UInt32 -> [%expr "0x%lx\n"]
223+
| UInt64 -> [%expr "0x%Lx\n"]
224+
in
225+
let hexdump_field f =
226+
if field_is_ignored f then
227+
[%expr ()]
228+
else
229+
let get_f = op_evar s (Op_get f) in
230+
let expr =
231+
match f.ty with
232+
|Prim p ->
233+
[%expr Printf.bprintf buf [%e prim_format_string p] ([%e get_f] v)]
234+
|Buffer (_,_) ->
235+
[%expr Printf.bprintf buf "<buffer %s>" [%e Ast.str (field_to_string f)];
236+
Cstruct.hexdump_to_buffer buf ([%e get_f] v)]
237+
in
238+
[%expr
239+
Printf.bprintf buf " %s = " [%e Ast.str f.field];
240+
[%e expr]]
241+
in
242+
[%expr fun buf v -> [%e Ast.sequence (List.map hexdump_field s.fields)]]
243+
244+
let op_expr loc s = function
245+
| Op_sizeof -> Ast.int s.len
246+
| Op_hexdump -> hexdump_expr s
247+
| Op_hexdump_to_buffer -> hexdump_to_buffer_expr s
248+
| Op_get f -> get_expr loc s f
249+
| Op_set f -> set_expr loc s f
250+
| Op_copy f ->
251+
let len = width_of_field f in
252+
[%expr fun src -> Cstruct.copy src [%e Ast.int f.off] [%e Ast.int len] ]
253+
| Op_blit f ->
254+
let len = width_of_field f in
255+
[%expr fun src srcoff dst ->
256+
Cstruct.blit src srcoff dst [%e Ast.int f.off] [%e Ast.int len]]
257+
258+
let field_ops_for f =
259+
if field_is_ignored f then
260+
[]
261+
else
262+
let if_buffer x =
263+
match f.ty with
264+
|Buffer (_,_) -> [x]
265+
|Prim _ -> []
266+
in
267+
List.concat
268+
[ [Op_get f]
269+
; if_buffer (Op_copy f)
270+
; [Op_set f]
271+
; if_buffer (Op_blit f)
272+
]
273+
274+
let ops_for s =
275+
( [Op_sizeof]
276+
@ List.concat (List.map field_ops_for s.fields)
277+
@ [Op_hexdump_to_buffer;
278+
Op_hexdump;
279+
])
280+
281+
(** Generate functions of the form {get/set}_<struct>_<field> *)
282+
let output_struct_one_endian loc s =
283+
List.map
284+
(fun op ->
285+
[%stri let[@ocaml.warning "-32"] [%p op_pvar s op] =
286+
[%e op_expr loc s op]])
287+
(ops_for s)
301288

302289
let output_struct _loc s =
303290
match s.endian with
@@ -315,12 +302,32 @@ let output_struct _loc s =
315302
]
316303
| _ -> output_struct_one_endian _loc s
317304

318-
let output_struct_sig _loc s =
319-
(* Generate signaturs of the form {get/set}_<struct>_<field> *)
320-
let expr = List.fold_left (fun a f ->
321-
a @ output_get_sig _loc s f @ output_set_sig _loc s f
322-
) [output_sizeof_sig _loc s] s.fields
323-
in expr @ output_hexdump_sig _loc s
305+
let type_of_get f =
306+
match f.ty with
307+
|Buffer (_,_) ->
308+
[%type: Cstruct.t -> Cstruct.t]
309+
|Prim prim ->
310+
let retf = type_of_int_field prim in
311+
[%type: Cstruct.t -> [%t retf]]
312+
313+
let op_typ = function
314+
| Op_sizeof -> [%type: int]
315+
| Op_hexdump_to_buffer -> [%type: Buffer.t -> Cstruct.t -> unit]
316+
| Op_hexdump -> [%type: Cstruct.t -> unit]
317+
| Op_get f -> type_of_get f
318+
| Op_set f -> type_of_set f
319+
| Op_copy _ -> [%type: Cstruct.t -> string]
320+
| Op_blit _ -> [%type: Cstruct.t -> int -> Cstruct.t -> unit]
321+
322+
(** Generate signatures of the form {get/set}_<struct>_<field> *)
323+
let output_struct_sig loc s =
324+
List.map
325+
(fun op ->
326+
Sig.value
327+
(Val.mk
328+
(Loc.mkloc (op_name s op) loc)
329+
(op_typ op)))
330+
(ops_for s)
324331

325332
let output_enum _loc name fields width ~sexp =
326333
let intfn,pattfn = match ty_of_string width with

ppx_test/basic.expected

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,8 @@ foo = {
88

99
}
1010
"\007\000,\000\000\190\239abcdefgh"
11+
with_ignored_field = {
12+
a = 0x1
13+
c = 0x3
14+
15+
}

ppx_test/basic.ml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,20 @@ type unused = {
7272
} [@@big_endian]
7373
]
7474

75+
let set_with_ignored_field__b = true
76+
77+
let _ : bool = set_with_ignored_field__b
78+
79+
[%%cstruct
80+
type with_ignored_field = {
81+
a : uint8_t;
82+
_b : uint8_t;
83+
c : uint8_t;
84+
} [@@little_endian]
85+
]
86+
87+
let _ : bool = set_with_ignored_field__b
88+
7589
let tests () =
7690
(* Test basic set/get functions *)
7791
let be = Cstruct.of_bigarray (Bigarray.(Array1.create char c_layout sizeof_foo)) in
@@ -151,6 +165,7 @@ let tests () =
151165
assert(get_foo_b be = 44);
152166
assert(get_foo_a be = 7);
153167
hexdump_foo be;
154-
print_endline (Sexplib.Sexp.to_string_hum (Cstruct.sexp_of_t be))
168+
print_endline (Sexplib.Sexp.to_string_hum (Cstruct.sexp_of_t be));
169+
hexdump_with_ignored_field (Cstruct.of_hex "010203")
155170

156171
let () = tests ()

0 commit comments

Comments
 (0)