(** Hexadecimal/String conversion where [Nil] is [""] *)
Module NilEmpty.
Fixpoint string_of_uint (d:uint) :=
match d with
| Nil => EmptyString
| D0 d => String "0" (string_of_uint d)
| D1 d => String "1" (string_of_uint d)
| D2 d => String "2" (string_of_uint d)
| D3 d => String "3" (string_of_uint d)
| D4 d => String "4" (string_of_uint d)
| D5 d => String "5" (string_of_uint d)
| D6 d => String "6" (string_of_uint d)
| D7 d => String "7" (string_of_uint d)
| D8 d => String "8" (string_of_uint d)
| D9 d => String "9" (string_of_uint d)
| Da d => String "a" (string_of_uint d)
| Db d => String "b" (string_of_uint d)
| Dc d => String "c" (string_of_uint d)
| Dd d => String "d" (string_of_uint d)
| De d => String "e" (string_of_uint d)
| Df d => String "f" (string_of_uint d)
end.
Fixpoint uint_of_string s :=
match s with
| EmptyString => Some Nil
| String a s => uint_of_char a (uint_of_string s)
end.
Definition string_of_int (d:int) :=
match d with
| Pos d => string_of_uint d
| Neg d => String "-" (string_of_uint d)
end.
Definition int_of_string s :=
match s with
| EmptyString => Some (Pos Nil)
| String a s' =>
if Ascii.eqb a "-" then option_map Neg (uint_of_string s')
else option_map Pos (uint_of_string s)
end.
(* NB: For the moment whitespace between - and digits are not accepted. And in this variant [int_of_string "-" = Some (Neg Nil)].  Compute int_of_string "-123456890123456890123456890123456890". Compute string_of_int (-123456890123456890123456890123456890). *)
(** Corresponding proofs *)

(* Specifications: *)
Lemma usu d :
uint_of_string (string_of_uint d) = Some d.
Lemma sus s d :
uint_of_string s = Some d -> string_of_uint d = s.
Lemma isi d : int_of_string (string_of_int d) = Some d.
Lemma sis s d :
int_of_string s = Some d -> string_of_int d = s.