Bryan Duxbury | 9dedce2 | 2011-01-26 23:31:19 +0000 | [diff] [blame] | 1 | open Thrift |
| 2 | |
| 3 | module T = Transport |
| 4 | |
| 5 | let c_0xff_32 = Int32.of_string "0xff" |
| 6 | |
| 7 | (* Copied from OCamlnet rtypes.ml *) |
| 8 | let encode_frame_size x = |
| 9 | let s = String.create 4 in |
| 10 | let n3 = Int32.to_int (Int32.shift_right_logical x 24) land 0xff in |
| 11 | let n2 = Int32.to_int (Int32.shift_right_logical x 16) land 0xff in |
| 12 | let n1 = Int32.to_int (Int32.shift_right_logical x 8) land 0xff in |
| 13 | let n0 = Int32.to_int (Int32.logand x c_0xff_32) in |
| 14 | String.unsafe_set s 0 (Char.unsafe_chr n3); |
| 15 | String.unsafe_set s 1 (Char.unsafe_chr n2); |
| 16 | String.unsafe_set s 2 (Char.unsafe_chr n1); |
| 17 | String.unsafe_set s 3 (Char.unsafe_chr n0); |
| 18 | s |
| 19 | |
| 20 | let decode_frame_size s = |
| 21 | let n3 = Int32.of_int (Char.code s.[0]) in |
| 22 | let n2 = Int32.of_int (Char.code s.[1]) in |
| 23 | let n1 = Int32.of_int (Char.code s.[2]) in |
| 24 | let n0 = Int32.of_int (Char.code s.[3]) in |
| 25 | Int32.logor |
| 26 | (Int32.shift_left n3 24) |
| 27 | (Int32.logor |
| 28 | (Int32.shift_left n2 16) |
| 29 | (Int32.logor |
| 30 | (Int32.shift_left n1 8) |
| 31 | n0)) |
| 32 | |
| 33 | class t ?(max_length=Sys.max_string_length) (transport: T.t) = |
| 34 | object (self) |
| 35 | inherit T.t |
| 36 | |
| 37 | method isOpen = transport#isOpen |
| 38 | method opn = transport#opn |
| 39 | method close = transport#close |
| 40 | |
| 41 | val mutable read_buf = None |
| 42 | val mutable read_buf_offset = 0 |
| 43 | val mutable write_buf = "" |
| 44 | |
| 45 | method private read_frame = |
| 46 | let len_buf = String.create 4 in |
| 47 | assert (transport#readAll len_buf 0 4 = 4); |
| 48 | |
| 49 | let size = Int32.to_int (decode_frame_size len_buf) in |
| 50 | |
| 51 | (if size < 0 |
| 52 | then failwith (Printf.sprintf "Read a negative frame size (%i)!" size)); |
| 53 | |
| 54 | (if size > max_length |
| 55 | then failwith (Printf.sprintf "Frame size (%i) larger than max length (%i)!" size max_length)); |
| 56 | |
| 57 | let buf = String.create size in |
| 58 | assert (transport#readAll buf 0 size = size); |
| 59 | read_buf <- Some buf; |
| 60 | read_buf_offset <- 0 |
| 61 | |
| 62 | method private read_from_frame frame buf off len = |
| 63 | let to_copy = min len ((String.length frame) - read_buf_offset) in |
| 64 | String.blit frame read_buf_offset buf off to_copy; |
| 65 | read_buf_offset <- read_buf_offset + to_copy; |
| 66 | to_copy |
| 67 | |
| 68 | method read buf off len = |
| 69 | match read_buf with |
| 70 | | Some frame -> |
| 71 | let i = self#read_from_frame frame buf off len in |
| 72 | if i > 0 |
| 73 | then i |
| 74 | else begin |
| 75 | self#read_frame; |
| 76 | self#read_from_frame frame buf off len |
| 77 | end |
| 78 | | None -> |
| 79 | self#read_frame; |
| 80 | self#read buf off len |
| 81 | |
| 82 | method write buf off len = |
| 83 | write_buf <- write_buf ^ (String.sub buf off len) |
| 84 | |
| 85 | method flush = |
| 86 | let encoded_size = encode_frame_size (Int32.of_int (String.length write_buf)) in |
| 87 | transport#write encoded_size 0 (String.length encoded_size); |
| 88 | transport#write write_buf 0 (String.length write_buf); |
| 89 | transport#flush; |
| 90 | write_buf <- "" |
| 91 | end |
| 92 | |
| 93 | |