pixelflut/sync/
client.rs

1//! Contains the sync client for pixelflut.
2use bufstream::BufStream;
3
4use std::io::{self, BufRead, Write};
5use std::net::{TcpStream, ToSocketAddrs};
6
7use crate::command::{Command, Response};
8use crate::error::PixelflutErrorKind;
9use crate::pixel::Pixel;
10use crate::{Color, PixelflutResult};
11
12/// Sync Pixelflut client.
13pub struct PixelflutClient {
14    stream: BufStream<TcpStream>,
15}
16
17impl PixelflutClient {
18    /// connects to a Pixelflut host at address `addr`
19    pub fn connect(addr: impl ToSocketAddrs) -> PixelflutResult<PixelflutClient> {
20        let stream = TcpStream::connect(addr)?;
21        Ok(PixelflutClient {
22            stream: BufStream::new(stream),
23        })
24    }
25
26    /// Asks the server for the dimensions of the canvas.
27    ///
28    /// A `SIZE` command is send to the server.
29    /// If the server replies with a `SIZE <width> <height>` packet,
30    /// the dimensions will be returned.
31    ///
32    /// # Returns
33    /// Ok((width, height)) on success
34    pub fn dimensions(&mut self) -> PixelflutResult<(u32, u32)> {
35        self.stream.write_fmt(format_args!("{}\n", Command::Size))?;
36        self.stream.flush()?;
37        let mut line = String::new();
38        let n = self.stream.read_line(&mut line)?;
39        if n > 0 {
40            let response: Response = line[0..n - 1].parse()?;
41            match response {
42                Response::Size { w, h } => Ok((w, h)),
43                Response::Error(_err) => Err(PixelflutErrorKind::ServerError.into()),
44            }
45        } else {
46            Err(io::Error::new(io::ErrorKind::UnexpectedEof, "expected size").into())
47        }
48    }
49
50    /// Writes a Pixel to the server.
51    ///
52    /// A buffered stream is used for sending.
53    /// The pixel is only send if the buffer is full or [flush] is called.
54    ///
55    /// [flush]: Self::flush
56    pub fn set(&mut self, x: u32, y: u32, color: impl Into<Color>) -> PixelflutResult<()> {
57        let pixel = Pixel::new((x, y).into(), color.into());
58        self.stream
59            .write_fmt(format_args!("{}\n", Command::Px(pixel)))?;
60        Ok(())
61    }
62
63    /// Flushes the internal buffer to the server.
64    pub fn flush(&mut self) -> PixelflutResult<()> {
65        self.stream.flush()?;
66        Ok(())
67    }
68}