File: custom_stream_backend.rs

package info (click to toggle)
rust-subversion 0.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 2,276 kB
  • sloc: makefile: 2
file content (132 lines) | stat: -rw-r--r-- 4,605 bytes parent folder | download
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
//! Example demonstrating custom stream backends in subversion-rs
//!
//! This example shows how to create custom stream implementations
//! that can be used with SVN's stream API.

use std::io::{Read, Write};
use subversion::io::{backend::*, Stream};

/// Custom backend that logs all operations
struct LoggingBackend<T> {
    inner: T,
    log_prefix: String,
}

impl<T> LoggingBackend<T> {
    fn new(inner: T, prefix: &str) -> Self {
        Self {
            inner,
            log_prefix: prefix.to_string(),
        }
    }
}

impl<T: Read + Write + Send + 'static> StreamBackend for LoggingBackend<T> {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, subversion::Error<'static>> {
        println!("{}: Reading up to {} bytes", self.log_prefix, buf.len());
        let n = self
            .inner
            .read(buf)
            .map_err(|e| subversion::Error::from_message(&e.to_string()))?;
        println!("{}: Read {} bytes", self.log_prefix, n);
        Ok(n)
    }

    fn write(&mut self, buf: &[u8]) -> Result<usize, subversion::Error<'static>> {
        println!("{}: Writing {} bytes", self.log_prefix, buf.len());
        let n = self
            .inner
            .write(buf)
            .map_err(|e| subversion::Error::from_message(&e.to_string()))?;
        println!("{}: Wrote {} bytes", self.log_prefix, n);
        Ok(n)
    }

    fn close(&mut self) -> Result<(), subversion::Error<'static>> {
        println!("{}: Closing stream", self.log_prefix);
        self.inner
            .flush()
            .map_err(|e| subversion::Error::from_message(&e.to_string()))?;
        Ok(())
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Custom Stream Backend Examples ===\n");

    // Example 1: BufferBackend (built-in) using IntoStream trait
    println!("1. Using BufferBackend with IntoStream:");
    use subversion::io::IntoStream;
    let backend = BufferBackend::from_vec(b"Hello, Subversion!".to_vec());
    let mut stream = backend.into_stream()?;

    let mut buf = vec![0u8; 18];
    let n = stream.read(&mut buf)?;
    println!("   Read {} bytes: {:?}", n, std::str::from_utf8(&buf[..n])?);

    // Example 2: Logging backend wrapping a buffer
    println!("\n2. Using LoggingBackend:");
    let buffer = std::io::Cursor::new(b"Logged data".to_vec());
    let logging_backend = LoggingBackend::new(buffer, "LOG");
    let mut stream = Stream::from_backend(logging_backend)?;

    let mut buf = vec![0u8; 11];
    stream.read(&mut buf)?;
    println!("   Result: {:?}", std::str::from_utf8(&buf)?);

    // Example 3: BufferBackend with write and reset
    println!("\n3. Using BufferBackend with write:");
    let backend = BufferBackend::new();
    // Both approaches are equivalent:
    // 1. Direct method call:
    let mut stream = Stream::from_backend(backend)?;
    // 2. Using IntoStream trait (would be: backend.into_stream()?)

    // Write data - using std::io::Write trait
    use std::io::Write;
    stream.write_all(b"Written data")?;
    stream.flush()?;

    // Note: BufferBackend supports both read and write
    println!("   Data successfully written to buffer backend");

    // Example 4: Using StreamBuilder
    println!("\n4. Using StreamBuilder:");
    use subversion::io::builder::StreamBuilder;

    let backend = BufferBackend::from_vec(b"Built with builder".to_vec());
    let mut stream = StreamBuilder::new(backend).buffer_size(1024).build()?;

    // Actually use the stream to demonstrate it works
    let mut buffer = vec![0u8; 18];
    let bytes_read = stream.read(&mut buffer)?;
    println!("   Stream created with builder pattern");
    println!(
        "   Read {} bytes: {:?}",
        bytes_read,
        String::from_utf8_lossy(&buffer[..bytes_read])
    );

    // Example 5: Read-only and Write-only backends
    println!("\n5. Using specialized backends:");

    // Read-only backend from stdin (in practice)
    let data = b"Read-only data";
    let reader = std::io::Cursor::new(data);
    let readonly = ReadOnlyBackend::new(reader);
    let mut stream = Stream::from_backend(readonly)?;

    let mut buf = vec![0u8; 14];
    let n = stream.read(&mut buf)?;
    println!("   Read-only: {:?}", std::str::from_utf8(&buf[..n])?);

    // Write-only backend to a buffer
    let writer = Vec::new();
    let writeonly = WriteOnlyBackend::new(writer);
    let mut stream = Stream::from_backend(writeonly)?;
    stream.write_all(b"Write-only data")?;
    println!("   Write-only: Data written successfully");

    println!("\n=== All examples completed successfully ===");
    Ok(())
}