magic: Use an iterator to generate the byte stream

Instead of explicitly writing the byte array for the magic packet
content, the `MagicPacket.send` method now delegates to
`MagicPacketIterator`. It collects the values the iterator produces,
which are determined based on the number of times the `next` method has
been called, into a vector, and then passes a slice of that vector to
the `send` method of the UDP socket.

Using a vector of course requires allocating space on the heap, so while
this method is probably not as efficient as the previous stack-allocated
static array, it is certainly cleaner and easier to understand.
master
Dustin 2018-08-16 22:53:50 -05:00
parent 84bf8c04cd
commit 9b0fb35ed5
1 changed files with 27 additions and 37 deletions

View File

@ -16,44 +16,34 @@ impl MagicPacket {
let socket = net::UdpSocket::bind("0.0.0.0:0")?; let socket = net::UdpSocket::bind("0.0.0.0:0")?;
socket.set_broadcast(true)?; socket.set_broadcast(true)?;
socket.connect("255.255.255.255:9")?; socket.connect("255.255.255.255:9")?;
socket.send(&self.to_buf()) let buf: Vec<u8> = self.iter().collect();
socket.send(&buf[..102])
} }
pub fn to_buf(&self) -> [u8; 102] { fn iter(&self) -> MagicPacketIterator {
[ MagicPacketIterator {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, packet: self,
self.addr[0], self.addr[1], self.addr[2], pos: 0,
self.addr[3], self.addr[4], self.addr[5], }
self.addr[0], self.addr[1], self.addr[2], }
self.addr[3], self.addr[4], self.addr[5], }
self.addr[0], self.addr[1], self.addr[2],
self.addr[3], self.addr[4], self.addr[5],
self.addr[0], self.addr[1], self.addr[2], struct MagicPacketIterator<'a> {
self.addr[3], self.addr[4], self.addr[5], packet: &'a MagicPacket<'a>,
self.addr[0], self.addr[1], self.addr[2], pos: usize,
self.addr[3], self.addr[4], self.addr[5], }
self.addr[0], self.addr[1], self.addr[2],
self.addr[3], self.addr[4], self.addr[5],
self.addr[0], self.addr[1], self.addr[2], impl<'a> Iterator for MagicPacketIterator<'a> {
self.addr[3], self.addr[4], self.addr[5], type Item = u8;
self.addr[0], self.addr[1], self.addr[2],
self.addr[3], self.addr[4], self.addr[5], fn next(&mut self) -> Option<Self::Item> {
self.addr[0], self.addr[1], self.addr[2], self.pos += 1;
self.addr[3], self.addr[4], self.addr[5], match self.pos {
self.addr[0], self.addr[1], self.addr[2], 1 ... 6 => Some(0xff),
self.addr[3], self.addr[4], self.addr[5], 7 ... 103 => Some(self.packet.addr[(self.pos - 7) % 6]),
self.addr[0], self.addr[1], self.addr[2], _ => None,
self.addr[3], self.addr[4], self.addr[5], }
self.addr[0], self.addr[1], self.addr[2],
self.addr[3], self.addr[4], self.addr[5],
self.addr[0], self.addr[1], self.addr[2],
self.addr[3], self.addr[4], self.addr[5],
self.addr[0], self.addr[1], self.addr[2],
self.addr[3], self.addr[4], self.addr[5],
self.addr[0], self.addr[1], self.addr[2],
self.addr[3], self.addr[4], self.addr[5],
self.addr[0], self.addr[1], self.addr[2],
self.addr[3], self.addr[4], self.addr[5],
]
} }
} }