1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use std::io::{self, Write};

#[derive(Debug, Clone)]
pub enum Error {
	Unspecified(&'static str),
}

enum PushGeneratorState {
	Initial,
	GeneratingMessage,
	Error(Error),
}

pub struct PushGenerator<'a> {
	target: &'a mut Write,
	state: PushGeneratorState,
}

impl<'a> PushGenerator<'a> {
	pub fn new<'x>(target: &'x mut Write) -> PushGenerator<'x> {
		PushGenerator {
			target: target,
			state: PushGeneratorState::Initial,
		}
	}

	pub fn next_message<'x, 'y: 'x+'y>(&'y mut self) -> Result<Message<'x, 'a>, Error> {
		match self.state {
			PushGeneratorState::Initial => {
				self.state = PushGeneratorState::GeneratingMessage;
				Ok(Message::new(self))
			},
			PushGeneratorState::GeneratingMessage => {
				Err(Error::Unspecified("Finish message before starting a new one"))
			},
			PushGeneratorState::Error(ref err) => Err(err.clone())
		}
	}
}

enum MessageState {
	BeforeFirstField,
	AfterFirstField,
	GeneratingField,
}

pub struct Message<'a, 'b: 'a+'b> {
	target: &'a mut PushGenerator<'b>,
	state: MessageState,
}

impl<'a, 'b> Message<'a, 'b> {
	fn new<'x, 'y: 'x+'y>(target: &'x mut PushGenerator<'y>) -> Message<'x, 'y> {
		Message {
			target: target,
			state: MessageState::BeforeFirstField,
		}
	}

	pub fn next_field<'x, 'y: 'x+'y>(&'y mut self) -> Result<Field<'x, 'a, 'b>, Error> {
		match self.state {
			MessageState::BeforeFirstField => {
				self.state = MessageState::GeneratingField;
				Ok(Field::new(self))
			},
			MessageState::AfterFirstField => {
				// TODO Handle failure. Should the generator get into a failed
				// state? Or are we able to try the same operation again?
				if let Err(_err) = self.target.target.write_all(&[' ' as u8]) { return Err(Error::Unspecified("Nested error")); }
				self.state = MessageState::GeneratingField;
				Ok(Field::new(self))
			},
			MessageState::GeneratingField =>
				Err(Error::Unspecified("You must close the previous field before starting a new one"))
		}
	}
}

impl<'a, 'b> Drop for Message<'a, 'b> {
	fn drop(&mut self) {
		self.target.state = match self.target.target.write_all(&['\n' as u8]) {
			Ok(()) => PushGeneratorState::Initial,
			Err(_err) => PushGeneratorState::Error(Error::Unspecified("Nested error")),
		}
	}
}

pub struct Field<'a, 'b: 'a + 'b, 'c: 'b + 'c> {
	target: &'a mut Message<'b, 'c>,
}

impl<'a, 'b, 'c> Field<'a, 'b, 'c> {
	fn new<'x, 'y, 'z>(target: &'x mut Message<'y, 'z>) -> Field<'x, 'y, 'z> {
		Field {
			target: target,
		}
	}
}

impl<'a, 'b, 'c> Drop for Field<'a, 'b, 'c> {
	fn drop(&mut self) {
		self.target.state = MessageState::AfterFirstField;
	}
}

impl<'a, 'b, 'c> Write for Field<'a, 'b, 'c> {
	fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
		self.target.target.target.write(buf)
	}

	fn flush(&mut self) -> io::Result<()> {
		self.target.target.target.flush()
	}
}

#[cfg(test)]
mod test {
	use std::io::Write;
	use pushgenerator::*;

	#[test]
	fn it_works() {
		let mut buffer = Vec::<u8>::new();

		{
			let mut generator = PushGenerator::new(&mut buffer);

			{
				let mut message = generator.next_message().unwrap();

				{
					let mut field = message.next_field().unwrap();
					field.write_all(b"0").unwrap();
				}

				{
					let mut field = message.next_field().unwrap();
					field.write_all(b"lol").unwrap();
				}
			}
		}

		assert_eq!(String::from("0 lol\n").into_bytes(), buffer);
	}
}