| 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 |  |