1 module hunt.http.codec.http.frame.PingFrame;
2 
3 import hunt.http.codec.http.frame.Frame;
4 import hunt.http.codec.http.frame.FrameType;
5 
6 import hunt.Exceptions;
7 
8 class PingFrame :Frame {
9 	static int PING_LENGTH = 8;
10 	private static byte[] EMPTY_PAYLOAD = new byte[8];
11 
12 	private byte[] payload;
13 	private bool reply;
14 
15 	/**
16 	 * Creates a PING frame with an empty payload.
17 	 *
18 	 * @param reply
19 	 *            whether this PING frame is a reply
20 	 */
21 	this(bool reply) {
22 		this(EMPTY_PAYLOAD, reply);
23 	}
24 
25 	/**
26 	 * Creates a PING frame with the given {@code long} {@code value} as
27 	 * payload.
28 	 *
29 	 * @param value
30 	 *            the value to use as a payload for this PING frame
31 	 * @param reply
32 	 *            whether this PING frame is a reply
33 	 */
34 	this(long value, bool reply) {
35 		this(toBytes(value), reply);
36 	}
37 
38 	/**
39 	 * Creates a PING frame with the given {@code payload}.
40 	 *
41 	 * @param payload
42 	 *            the payload for this PING frame
43 	 * @param reply
44 	 *            whether this PING frame is a reply
45 	 */
46 	this(byte[] payload, bool reply) {
47 		assert(payload !is null);
48 		super(FrameType.PING);
49 		this.payload = payload;
50 		if (payload.length != PING_LENGTH)
51 			throw new IllegalArgumentException("PING payload must be 8 bytes");
52 		this.reply = reply;
53 	}
54 
55 	byte[] getPayload() {
56 		return payload;
57 	}
58 
59 	long getPayloadAsLong() {
60 		return toLong(payload);
61 	}
62 
63 	bool isReply() {
64 		return reply;
65 	}
66 
67 	private static byte[] toBytes(long value) {
68 		byte[] result = new byte[8];
69 		for (size_t i = result.length - 1; i >= 0; --i) {
70 			result[i] = cast(byte) (value & 0xFF);
71 			value >>= 8;
72 		}
73 		return result;
74 	}
75 
76 	private static long toLong(byte[] payload) {
77 		long result = 0;
78 		for (size_t i = 0; i < 8; ++i) {
79 			result <<= 8;
80 			result |= (payload[i] & 0xFF);
81 		}
82 		return result;
83 	}
84 }