rust: как написать `impl` с обратными вызовами, которые ссылаются на внешние значения - PullRequest
0 голосов
/ 27 октября 2019

Я начал заниматься Rust несколько дней назад и столкнулся со следующей проблемой: я обнаружил библиотеку , которая позволяет мне превращать контуры шрифтов в SVG;на стороне пользователя часть кода выглядит следующим образом;обратите внимание, что я добавил здесь константу SCALE, которой нет в исходном примере кода, поставляемом с указанной библиотекой:

const SCALE: f32 = 0.5;
struct Builder<'a>(&'a mut svgtypes::Path);
impl ttf::OutlineBuilder for Builder<'_> {
  fn move_to( &mut self, x: f32, y: f32 ) { self.0.push_move_to(
    ( x  * SCALE ) as f64,
    ( y  * SCALE ) as f64 ); }
  ... }

...

let mut builder = Builder(path_buf);

затем объект builder передается функции, выполняющей тяжелыеснятие и вызывает обратно в метод реализации. Пока все хорошо: я хотел бы масштабировать пути, и приведенный выше код делает это. НО в нынешнем виде мне нужно определить const, чтобы сделать это, потому что Rust не позволяет методам ссылаться на внешние значения. Тем не менее, я хотел бы сделать динамический масштабирующий коэффициент, основанный на свойствах рассматриваемого шрифта.

Теперь, скажем, в JavaScript, я бы мог использовать фабричную функцию с закрытием над scale длясделайте это, или можно просто добавить свойство к объекту, обозначенному как self - существует множество способов решить это на языках сценариев. Ничто из вышеперечисленного не кажется простым в Rust. Возможно ли будет объявить новый тип структуры, которая принимает дополнительный параметр, как в

struct Builder<'a>(&'a mut svgtypes::Path, scale: f32 );
impl ttf::OutlineBuilder for Builder<'_> {
  fn move_to( &mut self, x: f32, y: f32 ) { self.0.push_move_to(
    ( x  * self.scale ) as f64,
    ( y  * self.scale ) as f64 ); }
  ... }

? Излишне говорить, что приведенный выше код не будет компилироваться.

1 Ответ

2 голосов
/ 28 октября 2019

Возможно ли будет объявить новый тип структуры, которая принимает дополнительный параметр

Да, было бы! Пример кода определяет Builder как Tuple Struct , что-то вроде структуры с безымянными полями. Хотя вы можете добавить к этому еще один элемент, который вы бы назвали self.1, вероятно, лучше всего перейти на обычную структуру:

struct Builder<'a> {
    path: &'a svgtypes::Path, 
    scale: f32
};

Затем вы можете получить доступ к шкале как self.scale:

impl ttf::OutlineBuilder for Builder<'_> {
    fn move_to( &mut self, x: f32, y: f32 ) { self.path.push_move_to(
    ( x  * self.scale ) as f64,
    ( y  * self.scale ) as f64 ); }
... }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...