#rust #rust-tokio #rust-iced
Вопрос:
Примечание: Я использую iced для графического TextInput
интерфейса и tokio для работы в сети TcpStream
У меня есть следующее:
#[derive(Debug, Clone)]
enum Message {
Session(Result<Connection, ConnectionError>), //Async Handler
SendMessage,
Send(Result<Connection, ConnectionError>), //Async Handler
InputChanged(String),
Button(usize, ButtonMessage),
None,
}
#[derive(Debug)]
enum ConnectionError {
ConnectError(usize),
SendError(usize),
}
#[derive(Debug)]
struct Connection {
stream: TcpStream,
loc: usize,
}
Проблема в том, что моя Connection
структура содержит TcpStream
то, что не может быть клонировано (в любом случае с точки зрения логистики клонировать ее было бы бессмысленно).
Поэтому я получаю ошибку…
>the trait bound `Connection: Clone` is not satisfied
--> srcmain.rs:27:10
|
27 | Session(Result<Connection, ConnectionError>), //Async Handler
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `Clone`
|
= note: required because of the requirements on the impl of `Clone` for `std::result::Result<Connection, ConnectionError>`
= note: required by `clone`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
>error[E0277]: the trait bound `ConnectionError: Clone` is not satisfied
--> srcmain.rs:27:10
|
27 | Session(Result<Connection, ConnectionError>), //Async Handler
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `Clone`
|
= note: required because of the requirements on the impl of `Clone` for `std::result::Result<Connection, ConnectionError>`
= note: required by `clone`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
>error[E0277]: the trait bound `Connection: Clone` is not satisfied
--> srcmain.rs:29:7
|
29 | Send(Result<Connection, ConnectionError>), //Async Handler
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `Clone`
|
= note: required because of the requirements on the impl of `Clone` for `std::result::Result<Connection, ConnectionError>`
= note: required by `clone`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
>error[E0277]: the trait bound `ConnectionError: Clone` is not satisfied
--> srcmain.rs:29:7
|
29 | Send(Result<Connection, ConnectionError>), //Async Handler
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `Clone`
|
= note: required because of the requirements on the impl of `Clone` for `std::result::Result<Connection, ConnectionError>`
= note: required by `clone`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
Поэтому я удалил Клона
#[derive(Debug)]
enum Message {
Session(Result<Connection, ConnectionError>), //Async Handler
SendMessage,
Send(Result<Connection, ConnectionError>), //Async Handler
InputChanged(String),
Button(usize, ButtonMessage),
None,
}
and get the following errors:
>the trait bound `Message: Clone` is not satisfied
--> srcmain.rs:516:15
|
516 | let input = TextInput::new(
| ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Message`
|
::: C:Usersbratl.cargoregistrysrcgithub.com-1ecc6299db9ec823iced_native-0.3.0srcwidgettext_input.rs:84:22
|
84 | F: 'static Fn(String) -> Message,
| --------------------- required by this bound in `iced_native::widget::text_input::TextInput::<'a, Message, Renderer>::new`
>error[E0599]: no method named `padding` found for struct `iced_native::widget::text_input::TextInput<'_, Message, iced_graphics::renderer::Renderer<iced_wgpu::backend::Backend>>` in the current scope
--> srcmain.rs:522:4
|
26 | enum Message {
| ------------ doesn't satisfy `Message: Clone`
...
522 | .padding(15)
| ^^^^^^^ private field, not a method
|
= note: the method `padding` exists but the following trait bounds were not satisfied:
`Message: Clone`
So I went to where the TextInput
was located and removed the Clone
as well.
#[derive(Debug)]
struct ClientAdminChatPaneContent {
scroll: scrollable::State,
input: text_input::State,
input_value: String,
}
#[derive(Debug)]
enum ChatPaneMessage {
InputChanged(String),
}
impl ClientAdminChatPaneContent {
fn new() -> Self {
ClientAdminChatPaneContent {
scroll: scrollable::State::new(),
input: text_input::State::new(),
input_value: String::from(""),
}
}
fn update(amp;mut self, message: ChatPaneMessage) {
match message {
ChatPaneMessage::InputChanged(value) => {
//println!("Input Changed: {}", value);
self.input_value = value;
}
}
}
fn view(amp;mut self) -> Element<Message> {
//Text Input
let input = TextInput::new(
amp;mut self.input,
"Message to Client",
amp;self.input_value,
Message::InputChanged,
)
.padding(15)
.size(30)
.on_submit(Message::SendMessage);
let text_input_container:Container<Message> = Container::new(input)
.width(Length::Fill)
.height(Length::Units(80))
.padding(10);
let scroll = Scrollable::new(amp;mut self.scroll)
.width(Length::Fill)
.spacing(10)
.align_items(Align::Start);
let scroll_container:Container<Message> = Container::new(scroll)
.width(Length::Fill)
.height(Length::Fill)
.padding(10);
let mut content = Column::new()
.spacing(5);
content = content.push(scroll_container);
content = content.push(text_input_container);
Container::new(content)
.width(Length::Fill)
.height(Length::Fill)
.padding(5)
.center_y()
.into()
}
fn clear_text(amp;mut self) {
self.input_value = String::from("");
}
}
И я получаю новую ошибку:
>the trait bound `Message: Clone` is not satisfied
--> srcmain.rs:516:15
|
516 | let input = TextInput::new(
| ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Message`
|
::: C:Usersbratl.cargoregistrysrcgithub.com-1ecc6299db9ec823iced_native-0.3.0srcwidgettext_input.rs:84:22
|
84 | F: 'static Fn(String) -> Message,
| --------------------- required by this bound in `iced_native::widget::text_input::TextInput::<'a, Message, Renderer>::new`
Что касается того, почему, я не уверен, почему let input = TextInput::new(
необходимо реализовать Clone
. Но, предполагая, что мне нужна эта структура для реализации клонирования, БЕЗ Message
реализации клонирования из-за TCP…
Как мне получить клон для определенного элемента, например a TextInput
, не выводя его для каждого отдельного элемента, или это совершенно другая проблема?
Комментарии:
1. Эти три факта не все могут быть правдой: (1)
Message
содержитConnection
. (2)Message
выводитClone
. (3)Connection
не реализуетсяClone
. На данный момент никто другой не может вам помочь: вы должны решить, какой из этих трех фактов должен дать, чтобы остальные могли остаться. Лично я подозреваю, что вам следует исключить (1) — в каком смысле имеет смысл, чтобы сообщение содержало соединение ? — но в конечном счете это определяется тем, как вы его используете. Нет никакого общего взлома или обходного пути; вещь либо естьClone
, либо ее нет. Я не знаю, что еще ты ожидаешь услышать.2. Это может помочь внести некоторую косвенность в данные, хранящиеся в ваших структурах, чтобы их можно было клонировать. Вы можете обернуть TcpStream в Rc (и RefCell, если вам нужно его изменить). Rc может быть клонирован без клонирования ссылки, которой он владеет, так как он просто увеличивает внутреннее количество ссылок
3. @trentcl Приношу свои извинения. Я на 100% понимаю, о чем вы говорите. И я полностью согласен с тем, что a
Message
не должно содержать aConnection
. Я пытался вернуть aConnection
из асинхронной функции, скажем, послеsend
функции дляTcpStream
. Теперь я понимаю, что это было ошибкой. Спасибо!4. Не нужно извиняться! Рад, что смог помочь, хотя бы в малой степени.
5. Не то чтобы я совсем понимал, как это исправить, или мысль о том, что я могу вернуть
Result<(), ConnectionError>
что-то вроде удара по мне. Понемногу. 🙂