Matching on types which implement a trait and therefore return it

I'm trying out some specific builder pattern. Please don't mind the design here -- it's a tryout.

I have a Renderer type which yields a method set_shape. The argument type given to the call should implement the empty trait IsRenderable. The login of the method then should differ between the struct types Rectangle and Circle which both implement the IsRenderable trait. Do not bother about the returning type.

#[derive(Clone, Copy)]
pub struct Rectangle {
    pub origin: Point,
    pub height: usize,
    pub width: usize,
}

trait IsRenderable {}

impl IsRenderBuilder for Rectangle {}

impl<'a> Renderer<'a> {
    // logic that needs lifetime 'a
    pub fn set_shape<T: IsRenderable>(shape: T) -> Box<IsRenderBuilder> {
        match shape {
            _ => panic!("WTF!"),
        }
    }
}

I'd like to do something like this. PSEUDO:

match shape {
    Rectangle => return RectangleShapeBuilder,
    Circle => return CircleShapeBuilder,
    _ => panic!("WTF!"),
}

Answers


Instead of using match, you should add a method on your IsRenderable trait that returns the appropriate builder for the particular implementor.

#[derive(Clone, Copy)]
pub struct Rectangle;

pub trait IsRenderable {
    fn new_builder(&self) -> Box<IsRenderBuilder>;
}

impl IsRenderable for Rectangle {
    fn new_builder(&self) -> Box<IsRenderBuilder> {
        Box::new(RectangleShapeBuilder)
    }
}

struct RectangleShapeBuilder;

pub trait IsRenderBuilder {}

impl IsRenderBuilder for RectangleShapeBuilder {}

pub fn set_shape<T: IsRenderable>(shape: T) -> Box<IsRenderBuilder> {
    shape.new_builder()
}

You might even use an associated type to avoid boxing the IsRenderBuilder:

#[derive(Clone, Copy)]
pub struct Rectangle;

pub trait IsRenderable {
    type Builder: IsRenderBuilder;

    fn new_builder(&self) -> Self::Builder;
}

impl IsRenderable for Rectangle {
    type Builder = RectangleShapeBuilder;

    fn new_builder(&self) -> Self::Builder {
        RectangleShapeBuilder
    }
}

pub struct RectangleShapeBuilder;

pub trait IsRenderBuilder {}

impl IsRenderBuilder for RectangleShapeBuilder {}

pub fn set_shape<T: IsRenderable>(shape: T) -> T::Builder {
    shape.new_builder()
}

Need Your Help

Set timestamps on a pivot model with Bookshelf.js

node.js orm bookshelf.js knex.js

I've got two Bookshelf models in a many-to-many relationship and I'd like to have timestamps updated when I'm attaching or detaching some relations.

Twitter API 1.1 does not giving correct time

php twitter

I am working on Twitter API 1.1. I want to fetch tweets from twitter for particular search. Here is my code :-