Skip to main content

computer_protocol/
files.rs

1use serde::{Deserialize, Serialize};
2
3/// Largest `write_file` content, in bytes.
4pub const MAX_WRITE_BYTES: usize = 10 * 1024 * 1024;
5
6/// Largest image `read_file` returns, in bytes.
7pub const MAX_IMAGE_BYTES: usize = 1024 * 1024;
8
9/// Body of `POST /sessions/{id}/files/list`.
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
11pub struct ListFilesRequest {
12    /// Folder to list. `None` means the session's working folder.
13    pub path: Option<String>,
14}
15
16/// What a folder entry is.
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
18#[serde(rename_all = "snake_case")]
19pub enum FileKind {
20    File,
21    Folder,
22    Symlink,
23    Other,
24}
25
26/// One entry of a folder.
27#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
28pub struct FileEntry {
29    pub name: String,
30    pub kind: FileKind,
31    /// Size in bytes. For a symlink, the size of the link itself.
32    pub size: u64,
33    /// Last change time as RFC 3339, when the system knows it.
34    pub modified: Option<String>,
35}
36
37/// Reply to `POST /sessions/{id}/files/list`.
38#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
39pub struct ListFilesReply {
40    /// Absolute path of the folder that was listed.
41    pub path: String,
42    /// Folders first, then files, each group sorted by name.
43    pub entries: Vec<FileEntry>,
44    /// Entries left out because the folder holds more than the limit.
45    pub omitted: u64,
46}
47
48/// Body of `POST /sessions/{id}/files/read`.
49#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
50pub struct ReadFileRequest {
51    pub path: String,
52    /// First line to return, counting from 1. Text files only.
53    pub offset: Option<u64>,
54    /// Number of lines to return. Text files only.
55    pub limit: Option<u64>,
56}
57
58/// Image formats `read_file` returns as images.
59#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
60#[serde(rename_all = "snake_case")]
61pub enum ImageType {
62    Png,
63    Jpeg,
64}
65
66impl ImageType {
67    #[must_use]
68    pub fn mime(self) -> &'static str {
69        match self {
70            Self::Png => "image/png",
71            Self::Jpeg => "image/jpeg",
72        }
73    }
74}
75
76/// Reply to `POST /sessions/{id}/files/read`.
77#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
78#[serde(tag = "kind", rename_all = "snake_case")]
79pub enum ReadFileReply {
80    Text {
81        /// Absolute path that was read.
82        path: String,
83        text: String,
84        /// How to read what was left out, when something was.
85        note: Option<String>,
86    },
87    Image {
88        path: String,
89        image_type: ImageType,
90        data_base64: String,
91    },
92}
93
94/// Body of `POST /sessions/{id}/files/write`.
95#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
96pub struct WriteFileRequest {
97    pub path: String,
98    pub content: String,
99}
100
101/// Reply to `POST /sessions/{id}/files/write`.
102#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
103pub struct WriteFileReply {
104    /// Absolute path that was written.
105    pub path: String,
106    pub bytes: u64,
107}