How about this?
(1) use ppx_enumerate to get a list of all flags and values
(2) decode is a simple fold with flag/mask
(3) pp using sexp (reversible) or show
??
open Sexplib0.Sexp_conv
type feature_mask_element =
| FEATURE1 [@value 1]
| FEATURE2 [@value 8]
| FEATURE3 [@value 0x400]
[@@deriving enum, show, enumerate, sexp]
type feature_mask = feature_mask_element list
[@@deriving show, sexp]
let all_masks =
all_of_feature_mask_element
|> List.map (fun f -> (f,feature_mask_element_to_enum f))
let decode_features x =
List.fold_left (fun acc (f,mask) ->
if x land mask <> 0 then (f::acc) else acc)
[] all_masks