ocaml-gopher/src/item.ml
orbifx 7b1ec728cf Introduce client & parser, switch to Dune
- Server and client now have dedicated module files
- Menu and Item have their own module files
- Wrote parsers for Menu and Item
- Switch from jbuilder to dune
- Introducing gopher client
- IPv6
2022-01-04 15:20:35 +00:00

80 lines
2.1 KiB
OCaml

type item_t =
| Text_file
| Submenu
| CCSO_nameserver
| Error
| Binhexencoded_file
| DOS_file
| Uuencoded_file
| Text_search
| Telnet
| Binary_file
| Alternate_server
| GIF_file
| Image_file
| Telnet_3270
| HTML_file
| Informational_message
| Sound_file
| Unknown
type t = { item_type : item_t; display_string : string; selector : string; hostname : string; port : int }
let char_of_type = function
| Text_file -> '0'
| Submenu -> '1'
| CCSO_nameserver -> '2'
| Error -> '3'
| Binhexencoded_file -> '4'
| DOS_file -> '5'
| Uuencoded_file -> '6'
| Text_search -> '7'
| Telnet -> '8'
| Binary_file -> '9'
| Alternate_server -> '+'
| GIF_file -> 'g'
| Image_file -> 'I'
| Telnet_3270 -> 'T'
| HTML_file -> 'h'
| Informational_message -> 'i'
| Sound_file -> 's'
| Unknown -> ' '
let type_of_char = function
| '0' -> Text_file
| '1' -> Submenu
| '2' -> CCSO_nameserver
| '3' -> Error
| '4' -> Binhexencoded_file
| '5' -> DOS_file
| '6' -> Uuencoded_file
| '7' -> Text_search
| '8' -> Telnet
| '9' -> Binary_file
| '+' -> Alternate_server
| 'g' -> GIF_file
| 'I' -> Image_file
| 'T' -> Telnet_3270
| 'h' -> HTML_file
| 'i' -> Informational_message
| 's' -> Sound_file
| _ -> Unknown
let line item_type user_display selector hostname port =
let (<+>) a b = a ^ "\t" ^ b in
(Char.escaped (char_of_type item_type)) ^ user_display <+> selector <+> hostname <+> string_of_int port <+> "\r\n"
let empty = { item_type = Unknown; display_string = ""; selector = ""; hostname = ""; port = 0 }
let of_line line =
let item_type = try type_of_char @@ String.get line 0 with _ -> Unknown in
if item_type = Unknown then empty
else (
let fields = String.split_on_char '\t' (String.sub line 1 (String.length line - 1)) in
let nth n = match List.nth_opt fields n with Some v -> v | None -> "" in
let port = try int_of_string (nth 3) with Failure _ -> 0 in
{ item_type; display_string = nth 0; selector = nth 1; hostname = nth 2; port }
)
let v item_type display_string selector hostname port =
{ item_type; display_string; selector; hostname; port }