Import protobuf-2.14.0

* Add OWNERS and Android.bp
* add generated version.rs into out

Bug: 143953733
Test: make
Change-Id: Ib53a973b74679c4dd78e2de2fa54141e55048c17
diff --git a/src/reflect/accessor.rs b/src/reflect/accessor.rs
new file mode 100644
index 0000000..8a586b2
--- /dev/null
+++ b/src/reflect/accessor.rs
@@ -0,0 +1,789 @@
+#![doc(hidden)]
+
+use std::collections::HashMap;
+use std::fmt;
+use std::hash::Hash;
+
+use core::message_down_cast;
+use core::Message;
+use enums::ProtobufEnum;
+use reflect::EnumValueDescriptor;
+use types::*;
+
+use repeated::RepeatedField;
+use singular::SingularField;
+use singular::SingularPtrField;
+
+use super::map::ReflectMap;
+use super::optional::ReflectOptional;
+use super::repeated::ReflectRepeated;
+use super::repeated::ReflectRepeatedEnum;
+use super::repeated::ReflectRepeatedMessage;
+use super::value::ProtobufValue;
+use super::value::ReflectValueRef;
+use super::ReflectFieldRef;
+
+/// this trait should not be used directly, use `FieldDescriptor` instead
+pub trait FieldAccessor {
+    fn name_generic(&self) -> &'static str;
+    fn has_field_generic(&self, m: &Message) -> bool;
+    fn len_field_generic(&self, m: &Message) -> usize;
+    // TODO: should it return default value or panic on unset field?
+    fn get_message_generic<'a>(&self, m: &'a Message) -> &'a Message;
+    fn get_enum_generic(&self, m: &Message) -> &'static EnumValueDescriptor;
+    fn get_str_generic<'a>(&self, m: &'a Message) -> &'a str;
+    fn get_bytes_generic<'a>(&self, m: &'a Message) -> &'a [u8];
+    fn get_u32_generic(&self, m: &Message) -> u32;
+    fn get_u64_generic(&self, m: &Message) -> u64;
+    fn get_i32_generic(&self, m: &Message) -> i32;
+    fn get_i64_generic(&self, m: &Message) -> i64;
+    fn get_bool_generic(&self, m: &Message) -> bool;
+    fn get_f32_generic(&self, m: &Message) -> f32;
+    fn get_f64_generic(&self, m: &Message) -> f64;
+
+    fn get_reflect<'a>(&self, m: &'a Message) -> ReflectFieldRef<'a>;
+}
+
+trait GetSingularMessage<M> {
+    fn get_message<'a>(&self, m: &'a M) -> &'a Message;
+}
+
+struct GetSingularMessageImpl<M, N> {
+    get: for<'a> fn(&'a M) -> &'a N,
+}
+
+impl<M: Message, N: Message + 'static> GetSingularMessage<M> for GetSingularMessageImpl<M, N> {
+    fn get_message<'a>(&self, m: &'a M) -> &'a Message {
+        (self.get)(m)
+    }
+}
+
+trait GetSingularEnum<M> {
+    fn get_enum(&self, m: &M) -> &'static EnumValueDescriptor;
+}
+
+struct GetSingularEnumImpl<M, E> {
+    get: fn(&M) -> E,
+}
+
+impl<M: Message, E: ProtobufEnum> GetSingularEnum<M> for GetSingularEnumImpl<M, E> {
+    fn get_enum(&self, m: &M) -> &'static EnumValueDescriptor {
+        (self.get)(m).descriptor()
+    }
+}
+
+trait GetRepeatedMessage<M> {
+    fn len_field(&self, m: &M) -> usize;
+    fn get_message_item<'a>(&self, m: &'a M, index: usize) -> &'a Message;
+    fn reflect_repeated_message<'a>(&self, m: &'a M) -> Box<ReflectRepeatedMessage<'a> + 'a>;
+}
+
+trait GetRepeatedEnum<M: Message + 'static> {
+    fn len_field(&self, m: &M) -> usize;
+    fn get_enum_item(&self, m: &M, index: usize) -> &'static EnumValueDescriptor;
+    fn reflect_repeated_enum<'a>(&self, m: &'a M) -> Box<ReflectRepeatedEnum<'a> + 'a>;
+}
+
+trait GetSetCopyFns<M> {
+    fn get_field<'a>(&self, m: &'a M) -> ReflectValueRef<'a>;
+}
+
+struct GetSetCopyFnsImpl<M, V: ProtobufValue + Copy> {
+    get: fn(&M) -> V,
+    _set: fn(&mut M, V),
+}
+
+impl<M, V: ProtobufValue + Copy> GetSetCopyFns<M> for GetSetCopyFnsImpl<M, V> {
+    fn get_field<'a>(&self, m: &'a M) -> ReflectValueRef<'a> {
+        (&(self.get)(m) as &ProtobufValue).as_ref_copy()
+    }
+}
+
+enum SingularGetSet<M> {
+    Copy(Box<GetSetCopyFns<M>>),
+    String(for<'a> fn(&'a M) -> &'a str, fn(&mut M, String)),
+    Bytes(for<'a> fn(&'a M) -> &'a [u8], fn(&mut M, Vec<u8>)),
+    Enum(Box<GetSingularEnum<M> + 'static>),
+    Message(Box<GetSingularMessage<M> + 'static>),
+}
+
+impl<M: Message + 'static> SingularGetSet<M> {
+    fn get_ref<'a>(&self, m: &'a M) -> ReflectValueRef<'a> {
+        match self {
+            &SingularGetSet::Copy(ref copy) => copy.get_field(m),
+            &SingularGetSet::String(get, _) => ReflectValueRef::String(get(m)),
+            &SingularGetSet::Bytes(get, _) => ReflectValueRef::Bytes(get(m)),
+            &SingularGetSet::Enum(ref get) => ReflectValueRef::Enum(get.get_enum(m)),
+            &SingularGetSet::Message(ref get) => ReflectValueRef::Message(get.get_message(m)),
+        }
+    }
+}
+
+trait FieldAccessor2<M, R: ?Sized>
+where
+    M: Message + 'static,
+{
+    fn get_field<'a>(&self, &'a M) -> &'a R;
+    fn mut_field<'a>(&self, &'a mut M) -> &'a mut R;
+}
+
+struct MessageGetMut<M, L>
+where
+    M: Message + 'static,
+{
+    get_field: for<'a> fn(&'a M) -> &'a L,
+    mut_field: for<'a> fn(&'a mut M) -> &'a mut L,
+}
+
+enum FieldAccessorFunctions<M> {
+    // up to 1.0.24 optional or required
+    SingularHasGetSet {
+        has: fn(&M) -> bool,
+        get_set: SingularGetSet<M>,
+    },
+    // protobuf 3 simple field
+    Simple(Box<FieldAccessor2<M, ProtobufValue>>),
+    // optional, required or message
+    Optional(Box<FieldAccessor2<M, ReflectOptional>>),
+    // repeated
+    Repeated(Box<FieldAccessor2<M, ReflectRepeated>>),
+    // protobuf 3 map
+    Map(Box<FieldAccessor2<M, ReflectMap>>),
+}
+
+impl<M> fmt::Debug for FieldAccessorFunctions<M> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            &FieldAccessorFunctions::SingularHasGetSet { .. } => {
+                write!(f, "SingularHasGetSet {{ .. }}")
+            }
+            &FieldAccessorFunctions::Simple(..) => write!(f, "Simple(..)"),
+            &FieldAccessorFunctions::Optional(..) => write!(f, "Optional(..)"),
+            &FieldAccessorFunctions::Repeated(..) => write!(f, "Repeated(..)"),
+            &FieldAccessorFunctions::Map(..) => write!(f, "Map(..)"),
+        }
+    }
+}
+
+struct FieldAccessorImpl<M> {
+    name: &'static str,
+    fns: FieldAccessorFunctions<M>,
+}
+
+impl<M: Message> FieldAccessorImpl<M> {
+    fn get_value_option<'a>(&self, m: &'a M) -> Option<ReflectValueRef<'a>> {
+        match self.fns {
+            FieldAccessorFunctions::Repeated(..) | FieldAccessorFunctions::Map(..) => {
+                panic!("repeated")
+            }
+            FieldAccessorFunctions::Simple(ref a) => Some(a.get_field(m).as_ref()),
+            FieldAccessorFunctions::Optional(ref a) => {
+                a.get_field(m).to_option().map(|v| v.as_ref())
+            }
+            FieldAccessorFunctions::SingularHasGetSet {
+                ref has,
+                ref get_set,
+            } => {
+                if !has(m) {
+                    None
+                } else {
+                    Some(get_set.get_ref(m))
+                }
+            }
+        }
+    }
+}
+
+impl<M: Message + 'static> FieldAccessor for FieldAccessorImpl<M> {
+    fn name_generic(&self) -> &'static str {
+        self.name
+    }
+
+    fn has_field_generic(&self, m: &Message) -> bool {
+        match self.fns {
+            FieldAccessorFunctions::SingularHasGetSet { has, .. } => has(message_down_cast(m)),
+            FieldAccessorFunctions::Optional(ref a) => {
+                a.get_field(message_down_cast(m)).to_option().is_some()
+            }
+            FieldAccessorFunctions::Simple(ref a) => {
+                a.get_field(message_down_cast(m)).is_non_zero()
+            }
+            FieldAccessorFunctions::Map(..) | FieldAccessorFunctions::Repeated(..) => {
+                panic!("has_xxx is not implemented for repeated");
+            }
+        }
+    }
+
+    fn len_field_generic(&self, m: &Message) -> usize {
+        match self.fns {
+            FieldAccessorFunctions::Repeated(ref a) => a.get_field(message_down_cast(m)).len(),
+            FieldAccessorFunctions::Map(ref a) => a.get_field(message_down_cast(m)).len(),
+            FieldAccessorFunctions::Simple(..)
+            | FieldAccessorFunctions::SingularHasGetSet { .. }
+            | FieldAccessorFunctions::Optional(..) => {
+                panic!("not a repeated field");
+            }
+        }
+    }
+
+    fn get_message_generic<'a>(&self, m: &'a Message) -> &'a Message {
+        match self.fns {
+            FieldAccessorFunctions::SingularHasGetSet {
+                get_set: SingularGetSet::Message(ref get),
+                ..
+            } => get.get_message(message_down_cast(m)),
+            FieldAccessorFunctions::Optional(ref t) => {
+                match t
+                    .get_field(message_down_cast(m))
+                    .to_option()
+                    .expect("field unset")
+                    .as_ref()
+                {
+                    ReflectValueRef::Message(m) => m,
+                    _ => panic!("not a message"),
+                }
+            }
+            ref fns => panic!("unknown accessor type: {:?}", fns),
+        }
+    }
+
+    fn get_enum_generic(&self, m: &Message) -> &'static EnumValueDescriptor {
+        match self.fns {
+            FieldAccessorFunctions::SingularHasGetSet {
+                get_set: SingularGetSet::Enum(ref get),
+                ..
+            } => get.get_enum(message_down_cast(m)),
+            _ => panic!(),
+        }
+    }
+
+    fn get_str_generic<'a>(&self, m: &'a Message) -> &'a str {
+        match self.get_value_option(message_down_cast(m)) {
+            Some(ReflectValueRef::String(v)) => v,
+            Some(_) => panic!("wrong type"),
+            None => "", // TODO: check type
+        }
+    }
+
+    fn get_bytes_generic<'a>(&self, m: &'a Message) -> &'a [u8] {
+        match self.get_value_option(message_down_cast(m)) {
+            Some(ReflectValueRef::Bytes(v)) => v,
+            Some(_) => panic!("wrong type"),
+            None => b"", // TODO: check type
+        }
+    }
+
+    fn get_u32_generic(&self, m: &Message) -> u32 {
+        match self.get_value_option(message_down_cast(m)) {
+            Some(ReflectValueRef::U32(v)) => v,
+            Some(_) => panic!("wrong type"),
+            None => 0, // TODO: check type
+        }
+    }
+
+    fn get_u64_generic(&self, m: &Message) -> u64 {
+        match self.get_value_option(message_down_cast(m)) {
+            Some(ReflectValueRef::U64(v)) => v,
+            Some(_) => panic!("wrong type"),
+            None => 0, // TODO: check type
+        }
+    }
+
+    fn get_i32_generic(&self, m: &Message) -> i32 {
+        match self.get_value_option(message_down_cast(m)) {
+            Some(ReflectValueRef::I32(v)) => v,
+            Some(_) => panic!("wrong type"),
+            None => 0, // TODO: check type
+        }
+    }
+
+    fn get_i64_generic(&self, m: &Message) -> i64 {
+        match self.get_value_option(message_down_cast(m)) {
+            Some(ReflectValueRef::I64(v)) => v,
+            Some(_) => panic!("wrong type"),
+            None => 0, // TODO: check type
+        }
+    }
+
+    fn get_f32_generic(&self, m: &Message) -> f32 {
+        match self.get_value_option(message_down_cast(m)) {
+            Some(ReflectValueRef::F32(v)) => v,
+            Some(_) => panic!("wrong type"),
+            None => 0.0, // TODO: check type
+        }
+    }
+
+    fn get_f64_generic(&self, m: &Message) -> f64 {
+        match self.get_value_option(message_down_cast(m)) {
+            Some(ReflectValueRef::F64(v)) => v,
+            Some(_) => panic!("wrong type"),
+            None => 0.0, // TODO: check type
+        }
+    }
+
+    fn get_bool_generic(&self, m: &Message) -> bool {
+        match self.get_value_option(message_down_cast(m)) {
+            Some(ReflectValueRef::Bool(v)) => v,
+            Some(_) => panic!("wrong type"),
+            None => false, // TODO: check type
+        }
+    }
+
+    fn get_reflect<'a>(&self, m: &'a Message) -> ReflectFieldRef<'a> {
+        match self.fns {
+            FieldAccessorFunctions::Repeated(ref accessor2) => {
+                ReflectFieldRef::Repeated(accessor2.get_field(message_down_cast(m)))
+            }
+            FieldAccessorFunctions::Map(ref accessor2) => {
+                ReflectFieldRef::Map(accessor2.get_field(message_down_cast(m)))
+            }
+            FieldAccessorFunctions::Optional(ref accessor2) => ReflectFieldRef::Optional(
+                accessor2
+                    .get_field(message_down_cast(m))
+                    .to_option()
+                    .map(|v| v.as_ref()),
+            ),
+            FieldAccessorFunctions::Simple(ref accessor2) => ReflectFieldRef::Optional({
+                let v = accessor2.get_field(message_down_cast(m));
+                if v.is_non_zero() {
+                    Some(v.as_ref())
+                } else {
+                    None
+                }
+            }),
+            FieldAccessorFunctions::SingularHasGetSet {
+                ref has,
+                ref get_set,
+            } => ReflectFieldRef::Optional(if has(message_down_cast(m)) {
+                Some(get_set.get_ref(message_down_cast(m)))
+            } else {
+                None
+            }),
+        }
+    }
+}
+
+// singular
+
+fn set_panic<A, B>(_: &mut A, _: B) {
+    panic!()
+}
+
+// TODO: make_singular_xxx_accessor are used only for oneof fields
+// oneof codegen should be changed
+
+pub fn make_singular_u32_accessor<M: Message + 'static>(
+    name: &'static str,
+    has: fn(&M) -> bool,
+    get: fn(&M) -> u32,
+) -> Box<FieldAccessor + 'static> {
+    Box::new(FieldAccessorImpl {
+        name: name,
+        fns: FieldAccessorFunctions::SingularHasGetSet {
+            has: has,
+            get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl {
+                get: get,
+                _set: set_panic,
+            })),
+        },
+    })
+}
+
+pub fn make_singular_i32_accessor<M: Message + 'static>(
+    name: &'static str,
+    has: fn(&M) -> bool,
+    get: fn(&M) -> i32,
+) -> Box<FieldAccessor + 'static> {
+    Box::new(FieldAccessorImpl {
+        name: name,
+        fns: FieldAccessorFunctions::SingularHasGetSet {
+            has: has,
+            get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl {
+                get: get,
+                _set: set_panic,
+            })),
+        },
+    })
+}
+
+pub fn make_singular_u64_accessor<M: Message + 'static>(
+    name: &'static str,
+    has: fn(&M) -> bool,
+    get: fn(&M) -> u64,
+) -> Box<FieldAccessor + 'static> {
+    Box::new(FieldAccessorImpl {
+        name: name,
+        fns: FieldAccessorFunctions::SingularHasGetSet {
+            has: has,
+            get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl {
+                get: get,
+                _set: set_panic,
+            })),
+        },
+    })
+}
+
+pub fn make_singular_i64_accessor<M: Message + 'static>(
+    name: &'static str,
+    has: fn(&M) -> bool,
+    get: fn(&M) -> i64,
+) -> Box<FieldAccessor + 'static> {
+    Box::new(FieldAccessorImpl {
+        name: name,
+        fns: FieldAccessorFunctions::SingularHasGetSet {
+            has: has,
+            get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl {
+                get: get,
+                _set: set_panic,
+            })),
+        },
+    })
+}
+
+pub fn make_singular_f32_accessor<M: Message + 'static>(
+    name: &'static str,
+    has: fn(&M) -> bool,
+    get: fn(&M) -> f32,
+) -> Box<FieldAccessor + 'static> {
+    Box::new(FieldAccessorImpl {
+        name: name,
+        fns: FieldAccessorFunctions::SingularHasGetSet {
+            has: has,
+            get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl {
+                get: get,
+                _set: set_panic,
+            })),
+        },
+    })
+}
+
+pub fn make_singular_f64_accessor<M: Message + 'static>(
+    name: &'static str,
+    has: fn(&M) -> bool,
+    get: fn(&M) -> f64,
+) -> Box<FieldAccessor + 'static> {
+    Box::new(FieldAccessorImpl {
+        name: name,
+        fns: FieldAccessorFunctions::SingularHasGetSet {
+            has: has,
+            get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl {
+                get: get,
+                _set: set_panic,
+            })),
+        },
+    })
+}
+
+pub fn make_singular_bool_accessor<M: Message + 'static>(
+    name: &'static str,
+    has: fn(&M) -> bool,
+    get: fn(&M) -> bool,
+) -> Box<FieldAccessor + 'static> {
+    Box::new(FieldAccessorImpl {
+        name: name,
+        fns: FieldAccessorFunctions::SingularHasGetSet {
+            has: has,
+            get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl {
+                get: get,
+                _set: set_panic,
+            })),
+        },
+    })
+}
+
+pub fn make_singular_enum_accessor<M: Message + 'static, E: ProtobufEnum + 'static>(
+    name: &'static str,
+    has: fn(&M) -> bool,
+    get: fn(&M) -> E,
+) -> Box<FieldAccessor + 'static> {
+    Box::new(FieldAccessorImpl {
+        name: name,
+        fns: FieldAccessorFunctions::SingularHasGetSet {
+            has: has,
+            get_set: SingularGetSet::Enum(Box::new(GetSingularEnumImpl { get: get })),
+        },
+    })
+}
+
+pub fn make_singular_string_accessor<M: Message + 'static>(
+    name: &'static str,
+    has: fn(&M) -> bool,
+    get: for<'a> fn(&'a M) -> &'a str,
+) -> Box<FieldAccessor + 'static> {
+    Box::new(FieldAccessorImpl {
+        name: name,
+        fns: FieldAccessorFunctions::SingularHasGetSet {
+            has: has,
+            get_set: SingularGetSet::String(get, set_panic),
+        },
+    })
+}
+
+pub fn make_singular_bytes_accessor<M: Message + 'static>(
+    name: &'static str,
+    has: fn(&M) -> bool,
+    get: for<'a> fn(&'a M) -> &'a [u8],
+) -> Box<FieldAccessor + 'static> {
+    Box::new(FieldAccessorImpl {
+        name: name,
+        fns: FieldAccessorFunctions::SingularHasGetSet {
+            has: has,
+            get_set: SingularGetSet::Bytes(get, set_panic),
+        },
+    })
+}
+
+pub fn make_singular_message_accessor<M: Message + 'static, F: Message + 'static>(
+    name: &'static str,
+    has: fn(&M) -> bool,
+    get: for<'a> fn(&'a M) -> &'a F,
+) -> Box<FieldAccessor + 'static> {
+    Box::new(FieldAccessorImpl {
+        name: name,
+        fns: FieldAccessorFunctions::SingularHasGetSet {
+            has: has,
+            get_set: SingularGetSet::Message(Box::new(GetSingularMessageImpl { get: get })),
+        },
+    })
+}
+
+// repeated
+
+impl<M, V> FieldAccessor2<M, ReflectRepeated> for MessageGetMut<M, Vec<V>>
+where
+    M: Message + 'static,
+    V: ProtobufValue + 'static,
+{
+    fn get_field<'a>(&self, m: &'a M) -> &'a ReflectRepeated {
+        (self.get_field)(m) as &ReflectRepeated
+    }
+
+    fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut ReflectRepeated {
+        (self.mut_field)(m) as &mut ReflectRepeated
+    }
+}
+
+pub fn make_vec_accessor<M, V>(
+    name: &'static str,
+    get_vec: for<'a> fn(&'a M) -> &'a Vec<V::Value>,
+    mut_vec: for<'a> fn(&'a mut M) -> &'a mut Vec<V::Value>,
+) -> Box<FieldAccessor + 'static>
+where
+    M: Message + 'static,
+    V: ProtobufType + 'static,
+{
+    Box::new(FieldAccessorImpl {
+        name: name,
+        fns: FieldAccessorFunctions::Repeated(Box::new(MessageGetMut::<M, Vec<V::Value>> {
+            get_field: get_vec,
+            mut_field: mut_vec,
+        })),
+    })
+}
+
+impl<M, V> FieldAccessor2<M, ReflectRepeated> for MessageGetMut<M, RepeatedField<V>>
+where
+    M: Message + 'static,
+    V: ProtobufValue + 'static,
+{
+    fn get_field<'a>(&self, m: &'a M) -> &'a ReflectRepeated {
+        (self.get_field)(m) as &ReflectRepeated
+    }
+
+    fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut ReflectRepeated {
+        (self.mut_field)(m) as &mut ReflectRepeated
+    }
+}
+
+pub fn make_repeated_field_accessor<M, V>(
+    name: &'static str,
+    get_vec: for<'a> fn(&'a M) -> &'a RepeatedField<V::Value>,
+    mut_vec: for<'a> fn(&'a mut M) -> &'a mut RepeatedField<V::Value>,
+) -> Box<FieldAccessor + 'static>
+where
+    M: Message + 'static,
+    V: ProtobufType + 'static,
+{
+    Box::new(FieldAccessorImpl {
+        name: name,
+        fns: FieldAccessorFunctions::Repeated(Box::new(MessageGetMut::<
+            M,
+            RepeatedField<V::Value>,
+        > {
+            get_field: get_vec,
+            mut_field: mut_vec,
+        })),
+    })
+}
+
+impl<M, V> FieldAccessor2<M, ReflectOptional> for MessageGetMut<M, Option<V>>
+where
+    M: Message + 'static,
+    V: ProtobufValue + Clone + 'static,
+{
+    fn get_field<'a>(&self, m: &'a M) -> &'a ReflectOptional {
+        (self.get_field)(m) as &ReflectOptional
+    }
+
+    fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut ReflectOptional {
+        (self.mut_field)(m) as &mut ReflectOptional
+    }
+}
+
+pub fn make_option_accessor<M, V>(
+    name: &'static str,
+    get_field: for<'a> fn(&'a M) -> &'a Option<V::Value>,
+    mut_field: for<'a> fn(&'a mut M) -> &'a mut Option<V::Value>,
+) -> Box<FieldAccessor + 'static>
+where
+    M: Message + 'static,
+    V: ProtobufType + 'static,
+{
+    Box::new(FieldAccessorImpl {
+        name: name,
+        fns: FieldAccessorFunctions::Optional(Box::new(MessageGetMut::<M, Option<V::Value>> {
+            get_field: get_field,
+            mut_field: mut_field,
+        })),
+    })
+}
+
+impl<M, V> FieldAccessor2<M, ReflectOptional> for MessageGetMut<M, SingularField<V>>
+where
+    M: Message + 'static,
+    V: ProtobufValue + Clone + 'static,
+{
+    fn get_field<'a>(&self, m: &'a M) -> &'a ReflectOptional {
+        (self.get_field)(m) as &ReflectOptional
+    }
+
+    fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut ReflectOptional {
+        (self.mut_field)(m) as &mut ReflectOptional
+    }
+}
+
+pub fn make_singular_field_accessor<M, V>(
+    name: &'static str,
+    get_field: for<'a> fn(&'a M) -> &'a SingularField<V::Value>,
+    mut_field: for<'a> fn(&'a mut M) -> &'a mut SingularField<V::Value>,
+) -> Box<FieldAccessor + 'static>
+where
+    M: Message + 'static,
+    V: ProtobufType + 'static,
+{
+    Box::new(FieldAccessorImpl {
+        name: name,
+        fns: FieldAccessorFunctions::Optional(Box::new(MessageGetMut::<
+            M,
+            SingularField<V::Value>,
+        > {
+            get_field: get_field,
+            mut_field: mut_field,
+        })),
+    })
+}
+
+impl<M, V> FieldAccessor2<M, ReflectOptional> for MessageGetMut<M, SingularPtrField<V>>
+where
+    M: Message + 'static,
+    V: ProtobufValue + Clone + 'static,
+{
+    fn get_field<'a>(&self, m: &'a M) -> &'a ReflectOptional {
+        (self.get_field)(m) as &ReflectOptional
+    }
+
+    fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut ReflectOptional {
+        (self.mut_field)(m) as &mut ReflectOptional
+    }
+}
+
+pub fn make_singular_ptr_field_accessor<M, V>(
+    name: &'static str,
+    get_field: for<'a> fn(&'a M) -> &'a SingularPtrField<V::Value>,
+    mut_field: for<'a> fn(&'a mut M) -> &'a mut SingularPtrField<V::Value>,
+) -> Box<FieldAccessor + 'static>
+where
+    M: Message + 'static,
+    V: ProtobufType + 'static,
+{
+    Box::new(FieldAccessorImpl {
+        name: name,
+        fns: FieldAccessorFunctions::Optional(Box::new(MessageGetMut::<
+            M,
+            SingularPtrField<V::Value>,
+        > {
+            get_field: get_field,
+            mut_field: mut_field,
+        })),
+    })
+}
+
+impl<M, V> FieldAccessor2<M, ProtobufValue> for MessageGetMut<M, V>
+where
+    M: Message + 'static,
+    V: ProtobufValue + Clone + 'static,
+{
+    fn get_field<'a>(&self, m: &'a M) -> &'a ProtobufValue {
+        (self.get_field)(m) as &ProtobufValue
+    }
+
+    fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut ProtobufValue {
+        (self.mut_field)(m) as &mut ProtobufValue
+    }
+}
+
+pub fn make_simple_field_accessor<M, V>(
+    name: &'static str,
+    get_field: for<'a> fn(&'a M) -> &'a V::Value,
+    mut_field: for<'a> fn(&'a mut M) -> &'a mut V::Value,
+) -> Box<FieldAccessor + 'static>
+where
+    M: Message + 'static,
+    V: ProtobufType + 'static,
+{
+    Box::new(FieldAccessorImpl {
+        name: name,
+        fns: FieldAccessorFunctions::Simple(Box::new(MessageGetMut::<M, V::Value> {
+            get_field: get_field,
+            mut_field: mut_field,
+        })),
+    })
+}
+
+impl<M, K, V> FieldAccessor2<M, ReflectMap> for MessageGetMut<M, HashMap<K, V>>
+where
+    M: Message + 'static,
+    K: ProtobufValue + 'static,
+    V: ProtobufValue + 'static,
+    K: Hash + Eq,
+{
+    fn get_field<'a>(&self, m: &'a M) -> &'a ReflectMap {
+        (self.get_field)(m) as &ReflectMap
+    }
+
+    fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut ReflectMap {
+        (self.mut_field)(m) as &mut ReflectMap
+    }
+}
+
+pub fn make_map_accessor<M, K, V>(
+    name: &'static str,
+    get_field: for<'a> fn(&'a M) -> &'a HashMap<K::Value, V::Value>,
+    mut_field: for<'a> fn(&'a mut M) -> &'a mut HashMap<K::Value, V::Value>,
+) -> Box<FieldAccessor + 'static>
+where
+    M: Message + 'static,
+    K: ProtobufType + 'static,
+    V: ProtobufType + 'static,
+    <K as ProtobufType>::Value: Hash + Eq,
+{
+    Box::new(FieldAccessorImpl {
+        name: name,
+        fns: FieldAccessorFunctions::Map(Box::new(
+            MessageGetMut::<M, HashMap<K::Value, V::Value>> {
+                get_field: get_field,
+                mut_field: mut_field,
+            },
+        )),
+    })
+}
diff --git a/src/reflect/enums.rs b/src/reflect/enums.rs
new file mode 100644
index 0000000..e4ba4f6
--- /dev/null
+++ b/src/reflect/enums.rs
@@ -0,0 +1,127 @@
+use descriptor::EnumDescriptorProto;
+use descriptor::EnumValueDescriptorProto;
+use descriptor::FileDescriptorProto;
+use descriptorx::find_enum_by_rust_name;
+use reflect::find_message_or_enum::find_message_or_enum;
+use reflect::find_message_or_enum::MessageOrEnum;
+use std::collections::HashMap;
+use ProtobufEnum;
+
+/// Description for enum variant.
+///
+/// Used in reflection.
+#[derive(Clone, Debug)]
+pub struct EnumValueDescriptor {
+    proto: &'static EnumValueDescriptorProto,
+}
+
+impl Copy for EnumValueDescriptor {}
+
+impl EnumValueDescriptor {
+    /// Name of enum variant as specified in proto file
+    pub fn name(&self) -> &'static str {
+        self.proto.get_name()
+    }
+
+    /// `i32` value of the enum variant
+    pub fn value(&self) -> i32 {
+        self.proto.get_number()
+    }
+}
+
+/// Dynamic representation of enum type.
+///
+/// Can be used in reflective operations.
+pub struct EnumDescriptor {
+    proto: &'static EnumDescriptorProto,
+    values: Vec<EnumValueDescriptor>,
+
+    index_by_name: HashMap<String, usize>,
+    index_by_number: HashMap<i32, usize>,
+}
+
+impl EnumDescriptor {
+    /// Enum name as given in `.proto` file
+    pub fn name(&self) -> &'static str {
+        self.proto.get_name()
+    }
+
+    /// `EnumDescriptor` for enum type
+    pub fn for_type<E: ProtobufEnum>() -> &'static EnumDescriptor {
+        E::enum_descriptor_static()
+    }
+
+    /// Create new enum descriptor.
+    ///
+    /// This function is called by generated code, and should not be called manually.
+    #[deprecated(
+        since = "2.12",
+        note = "Please regenerate .rs files from .proto files to use newer APIs"
+    )]
+    pub fn new(rust_name: &'static str, file: &'static FileDescriptorProto) -> EnumDescriptor {
+        let proto = find_enum_by_rust_name(file, rust_name);
+        let mut index_by_name = HashMap::new();
+        let mut index_by_number = HashMap::new();
+        for (i, v) in proto.en.get_value().iter().enumerate() {
+            index_by_number.insert(v.get_number(), i);
+            index_by_name.insert(v.get_name().to_string(), i);
+        }
+        EnumDescriptor {
+            proto: proto.en,
+            values: proto
+                .en
+                .get_value()
+                .iter()
+                .map(|v| EnumValueDescriptor { proto: v })
+                .collect(),
+            index_by_name: index_by_name,
+            index_by_number: index_by_number,
+        }
+    }
+
+    /// Create new enum descriptor.
+    ///
+    /// This function is called by generated code, and should not be called manually.
+    pub fn new_pb_name<E>(
+        name_in_file: &'static str,
+        file: &'static FileDescriptorProto,
+    ) -> EnumDescriptor
+    where
+        E: ProtobufEnum,
+    {
+        let (_path_to_package, proto) = match find_message_or_enum(file, name_in_file) {
+            (path_to_package, MessageOrEnum::Enum(e)) => (path_to_package, e),
+            (_, MessageOrEnum::Message(_)) => panic!("not an enum"),
+        };
+
+        let mut index_by_name = HashMap::new();
+        let mut index_by_number = HashMap::new();
+        for (i, v) in proto.get_value().iter().enumerate() {
+            index_by_number.insert(v.get_number(), i);
+            index_by_name.insert(v.get_name().to_string(), i);
+        }
+        EnumDescriptor {
+            proto,
+            values: proto
+                .get_value()
+                .iter()
+                .map(|v| EnumValueDescriptor { proto: v })
+                .collect(),
+            index_by_name: index_by_name,
+            index_by_number: index_by_number,
+        }
+    }
+
+    /// Find enum value by name
+    pub fn value_by_name<'a>(&'a self, name: &str) -> &'a EnumValueDescriptor {
+        // TODO: clone is weird
+        let &index = self.index_by_name.get(&name.to_string()).unwrap();
+        &self.values[index]
+    }
+
+    /// Find enum value by number
+    pub fn value_by_number<'a>(&'a self, number: i32) -> &'a EnumValueDescriptor {
+        let &index = self.index_by_number.get(&number).unwrap();
+        &self.values[index]
+    }
+}
diff --git a/src/reflect/field.rs b/src/reflect/field.rs
new file mode 100644
index 0000000..ecac510
--- /dev/null
+++ b/src/reflect/field.rs
@@ -0,0 +1,191 @@
+use descriptor::{FieldDescriptorProto, FieldDescriptorProto_Label};
+use reflect::accessor::FieldAccessor;
+use reflect::map::ReflectMap;
+use reflect::repeated::ReflectRepeated;
+use reflect::{EnumValueDescriptor, ReflectValueRef};
+use Message;
+
+/// Reference to a value stored in a field, optional, repeated or map.
+// TODO: implement Eq
+pub enum ReflectFieldRef<'a> {
+    /// Singular field, optional or required in proto3 and just plain field in proto3
+    Optional(Option<ReflectValueRef<'a>>),
+    /// Repeated field
+    Repeated(&'a ReflectRepeated),
+    /// Map field
+    Map(&'a ReflectMap),
+}
+
+/// Field descriptor.
+///
+/// Can be used for runtime reflection.
+pub struct FieldDescriptor {
+    proto: &'static FieldDescriptorProto,
+    accessor: Box<FieldAccessor + 'static>,
+}
+
+impl FieldDescriptor {
+    pub(crate) fn new(
+        accessor: Box<FieldAccessor + 'static>,
+        proto: &'static FieldDescriptorProto,
+    ) -> FieldDescriptor {
+        assert_eq!(proto.get_name(), accessor.name_generic());
+        FieldDescriptor { proto, accessor }
+    }
+
+    /// Get `.proto` description of field
+    pub fn proto(&self) -> &'static FieldDescriptorProto {
+        self.proto
+    }
+
+    /// Field name as specified in `.proto` file
+    pub fn name(&self) -> &'static str {
+        self.proto.get_name()
+    }
+
+    /// If this field repeated?
+    pub fn is_repeated(&self) -> bool {
+        self.proto.get_label() == FieldDescriptorProto_Label::LABEL_REPEATED
+    }
+
+    /// Check if field is set in given message.
+    ///
+    /// For repeated field or map field return `true` if
+    /// collection is not empty.
+    ///
+    /// # Panics
+    ///
+    /// If this field belongs to a different message type.
+    pub fn has_field(&self, m: &Message) -> bool {
+        self.accessor.has_field_generic(m)
+    }
+
+    /// Return length of repeated field.
+    ///
+    /// For singualar field return `1` if field is set and `0` otherwise.
+    ///
+    /// # Panics
+    ///
+    /// If this field belongs to a different message type.
+    pub fn len_field(&self, m: &dyn Message) -> usize {
+        self.accessor.len_field_generic(m)
+    }
+
+    /// Get message field or default instance if field is unset.
+    ///
+    /// # Panics
+    /// If this field belongs to a different message type or
+    /// field type is not message.
+    pub fn get_message<'a>(&self, m: &'a dyn Message) -> &'a dyn Message {
+        self.accessor.get_message_generic(m)
+    }
+
+    /// Get `enum` field.
+    ///
+    /// # Panics
+    ///
+    /// If this field belongs to a different message type
+    /// or field type is not singular `enum`.
+    pub fn get_enum(&self, m: &dyn Message) -> &'static EnumValueDescriptor {
+        self.accessor.get_enum_generic(m)
+    }
+
+    /// Get `string` field.
+    ///
+    /// # Panics
+    ///
+    /// If this field belongs to a different message type
+    /// or field type is not singular `string`.
+    pub fn get_str<'a>(&self, m: &'a dyn Message) -> &'a str {
+        self.accessor.get_str_generic(m)
+    }
+
+    /// Get `bytes` field.
+    ///
+    /// # Panics
+    ///
+    /// If this field belongs to a different message type
+    /// or field type is not singular `bytes`.
+    pub fn get_bytes<'a>(&self, m: &'a dyn Message) -> &'a [u8] {
+        self.accessor.get_bytes_generic(m)
+    }
+
+    /// Get `u32` field.
+    ///
+    /// # Panics
+    ///
+    /// If this field belongs to a different message type
+    /// or field type is not singular `u32`.
+    pub fn get_u32(&self, m: &dyn Message) -> u32 {
+        self.accessor.get_u32_generic(m)
+    }
+
+    /// Get `u64` field.
+    ///
+    /// # Panics
+    ///
+    /// If this field belongs to a different message type
+    /// or field type is not singular `u64`.
+    pub fn get_u64(&self, m: &dyn Message) -> u64 {
+        self.accessor.get_u64_generic(m)
+    }
+
+    /// Get `i32` field.
+    ///
+    /// # Panics
+    ///
+    /// If this field belongs to a different message type
+    /// or field type is not singular `i32`.
+    pub fn get_i32(&self, m: &dyn Message) -> i32 {
+        self.accessor.get_i32_generic(m)
+    }
+
+    /// Get `i64` field.
+    ///
+    /// # Panics
+    ///
+    /// If this field belongs to a different message type
+    /// or field type is not singular `i64`.
+    pub fn get_i64(&self, m: &dyn Message) -> i64 {
+        self.accessor.get_i64_generic(m)
+    }
+
+    /// Get `bool` field.
+    ///
+    /// # Panics
+    ///
+    /// If this field belongs to a different message type or
+    /// field type is not singular `bool`.
+    pub fn get_bool(&self, m: &dyn Message) -> bool {
+        self.accessor.get_bool_generic(m)
+    }
+
+    /// Get `float` field.
+    ///
+    /// # Panics
+    ///
+    /// If this field belongs to a different message type or
+    /// field type is not singular `float`.
+    pub fn get_f32(&self, m: &dyn Message) -> f32 {
+        self.accessor.get_f32_generic(m)
+    }
+
+    /// Get `double` field.
+    ///
+    /// # Panics
+    ///
+    /// If this field belongs to a different message type
+    /// or field type is not singular `double`.
+    pub fn get_f64(&self, m: &dyn Message) -> f64 {
+        self.accessor.get_f64_generic(m)
+    }
+
+    /// Get field of any type.
+    ///
+    /// # Panics
+    ///
+    /// If this field belongs to a different message type.
+    pub fn get_reflect<'a>(&self, m: &'a dyn Message) -> ReflectFieldRef<'a> {
+        self.accessor.get_reflect(m)
+    }
+}
diff --git a/src/reflect/find_message_or_enum.rs b/src/reflect/find_message_or_enum.rs
new file mode 100644
index 0000000..7ee3915
--- /dev/null
+++ b/src/reflect/find_message_or_enum.rs
@@ -0,0 +1,62 @@
+use crate::descriptor::DescriptorProto;
+use crate::descriptor::EnumDescriptorProto;
+use crate::descriptor::FileDescriptorProto;
+
+pub(crate) enum MessageOrEnum<'a> {
+    Message(&'a DescriptorProto),
+    Enum(&'a EnumDescriptorProto),
+}
+
+impl<'a> MessageOrEnum<'a> {
+    fn from_two_options(
+        m: Option<&'a DescriptorProto>,
+        e: Option<&'a EnumDescriptorProto>,
+    ) -> MessageOrEnum<'a> {
+        match (m, e) {
+            (Some(_), Some(_)) => panic!("enum and message with the same name"),
+            (Some(m), None) => MessageOrEnum::Message(m),
+            (None, Some(e)) => MessageOrEnum::Enum(e),
+            (None, None) => panic!("not found"),
+        }
+    }
+}
+
+pub(crate) fn find_message_or_enum<'a>(
+    file: &'a FileDescriptorProto,
+    name_to_package: &str,
+) -> (String, MessageOrEnum<'a>) {
+    let mut path = name_to_package.split('.');
+    let first = path.next().unwrap();
+    let child_message = file
+        .get_message_type()
+        .iter()
+        .find(|m| m.get_name() == first);
+    let child_enum = file.get_enum_type().iter().find(|e| e.get_name() == first);
+
+    let mut package_to_name = String::new();
+    let mut me = MessageOrEnum::from_two_options(child_message, child_enum);
+
+    for name in path {
+        let message = match me {
+            MessageOrEnum::Message(m) => m,
+            MessageOrEnum::Enum(_) => panic!("enum has no children"),
+        };
+
+        if !package_to_name.is_empty() {
+            package_to_name.push_str(".");
+        }
+        package_to_name.push_str(message.get_name());
+
+        let child_message = message
+            .get_nested_type()
+            .iter()
+            .find(|m| m.get_name() == name);
+        let child_enum = message
+            .get_enum_type()
+            .iter()
+            .find(|e| e.get_name() == name);
+        me = MessageOrEnum::from_two_options(child_message, child_enum)
+    }
+
+    (package_to_name, me)
+}
diff --git a/src/reflect/map.rs b/src/reflect/map.rs
new file mode 100644
index 0000000..9f03123
--- /dev/null
+++ b/src/reflect/map.rs
@@ -0,0 +1,66 @@
+use std::collections::hash_map;
+use std::collections::HashMap;
+use std::hash::Hash;
+
+use super::value::ProtobufValue;
+
+/// Implemented for `HashMap` with appropriate keys and values
+pub trait ReflectMap: 'static {
+    fn reflect_iter(&self) -> ReflectMapIter;
+
+    fn len(&self) -> usize;
+}
+
+impl<K: ProtobufValue + Eq + Hash + 'static, V: ProtobufValue + 'static> ReflectMap
+    for HashMap<K, V>
+{
+    fn reflect_iter<'a>(&'a self) -> ReflectMapIter<'a> {
+        ReflectMapIter {
+            imp: Box::new(ReflectMapIterImpl::<'a, K, V> { iter: self.iter() }),
+        }
+    }
+
+    fn len(&self) -> usize {
+        HashMap::len(self)
+    }
+}
+
+trait ReflectMapIterTrait<'a> {
+    fn next(&mut self) -> Option<(&'a ProtobufValue, &'a ProtobufValue)>;
+}
+
+struct ReflectMapIterImpl<'a, K: Eq + Hash + 'static, V: 'static> {
+    iter: hash_map::Iter<'a, K, V>,
+}
+
+impl<'a, K: ProtobufValue + Eq + Hash + 'static, V: ProtobufValue + 'static> ReflectMapIterTrait<'a>
+    for ReflectMapIterImpl<'a, K, V>
+{
+    fn next(&mut self) -> Option<(&'a ProtobufValue, &'a ProtobufValue)> {
+        match self.iter.next() {
+            Some((k, v)) => Some((k as &ProtobufValue, v as &ProtobufValue)),
+            None => None,
+        }
+    }
+}
+
+pub struct ReflectMapIter<'a> {
+    imp: Box<ReflectMapIterTrait<'a> + 'a>,
+}
+
+impl<'a> Iterator for ReflectMapIter<'a> {
+    type Item = (&'a ProtobufValue, &'a ProtobufValue);
+
+    fn next(&mut self) -> Option<(&'a ProtobufValue, &'a ProtobufValue)> {
+        self.imp.next()
+    }
+}
+
+impl<'a> IntoIterator for &'a ReflectMap {
+    type IntoIter = ReflectMapIter<'a>;
+    type Item = (&'a ProtobufValue, &'a ProtobufValue);
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.reflect_iter()
+    }
+}
diff --git a/src/reflect/message.rs b/src/reflect/message.rs
new file mode 100644
index 0000000..c35a854
--- /dev/null
+++ b/src/reflect/message.rs
@@ -0,0 +1,223 @@
+use descriptor::{DescriptorProto, FileDescriptorProto};
+use descriptorx::find_message_by_rust_name;
+use reflect::accessor::FieldAccessor;
+use reflect::find_message_or_enum::find_message_or_enum;
+use reflect::find_message_or_enum::MessageOrEnum;
+use reflect::FieldDescriptor;
+use std::collections::HashMap;
+use std::marker;
+use Message;
+
+trait MessageFactory: Send + Sync + 'static {
+    fn new_instance(&self) -> Box<dyn Message>;
+}
+
+struct MessageFactoryImpl<M>(marker::PhantomData<M>);
+
+impl<M> MessageFactory for MessageFactoryImpl<M>
+where
+    M: 'static + Message + Default + Clone + PartialEq,
+{
+    fn new_instance(&self) -> Box<dyn Message> {
+        let m: M = Default::default();
+        Box::new(m)
+    }
+}
+
+/// Dynamic message type
+pub struct MessageDescriptor {
+    full_name: String,
+    proto: &'static DescriptorProto,
+    factory: &'static dyn MessageFactory,
+    fields: Vec<FieldDescriptor>,
+
+    index_by_name: HashMap<String, usize>,
+    index_by_number: HashMap<u32, usize>,
+}
+
+impl MessageDescriptor {
+    /// Get underlying `DescriptorProto` object.
+    pub fn get_proto(&self) -> &DescriptorProto {
+        self.proto
+    }
+
+    /// Get a message descriptor for given message type
+    pub fn for_type<M: Message>() -> &'static MessageDescriptor {
+        M::descriptor_static()
+    }
+
+    fn compute_full_name(package: &str, path_to_package: &str, proto: &DescriptorProto) -> String {
+        let mut full_name = package.to_owned();
+        if path_to_package.len() != 0 {
+            if full_name.len() != 0 {
+                full_name.push('.');
+            }
+            full_name.push_str(path_to_package);
+        }
+        if full_name.len() != 0 {
+            full_name.push('.');
+        }
+        full_name.push_str(proto.get_name());
+        full_name
+    }
+
+    // Non-generic part of `new` is a separate function
+    // to reduce code bloat from multiple instantiations.
+    fn new_non_generic_by_rust_name(
+        rust_name: &'static str,
+        fields: Vec<Box<FieldAccessor + 'static>>,
+        file: &'static FileDescriptorProto,
+        factory: &'static dyn MessageFactory,
+    ) -> MessageDescriptor {
+        let proto = find_message_by_rust_name(file, rust_name);
+
+        let mut field_proto_by_name = HashMap::new();
+        for field_proto in proto.message.get_field() {
+            field_proto_by_name.insert(field_proto.get_name(), field_proto);
+        }
+
+        let mut index_by_name = HashMap::new();
+        let mut index_by_number = HashMap::new();
+        for (i, f) in proto.message.get_field().iter().enumerate() {
+            index_by_number.insert(f.get_number() as u32, i);
+            index_by_name.insert(f.get_name().to_string(), i);
+        }
+
+        let mut full_name = file.get_package().to_string();
+        if full_name.len() > 0 {
+            full_name.push('.');
+        }
+        full_name.push_str(proto.message.get_name());
+
+        MessageDescriptor {
+            full_name: full_name,
+            proto: proto.message,
+            factory,
+            fields: fields
+                .into_iter()
+                .map(|f| {
+                    let proto = *field_proto_by_name.get(&f.name_generic()).unwrap();
+                    FieldDescriptor::new(f, proto)
+                })
+                .collect(),
+            index_by_name,
+            index_by_number,
+        }
+    }
+
+    // Non-generic part of `new` is a separate function
+    // to reduce code bloat from multiple instantiations.
+    fn new_non_generic_by_pb_name(
+        protobuf_name_to_package: &'static str,
+        fields: Vec<Box<FieldAccessor + 'static>>,
+        file_descriptor_proto: &'static FileDescriptorProto,
+        factory: &'static dyn MessageFactory,
+    ) -> MessageDescriptor {
+        let (path_to_package, proto) =
+            match find_message_or_enum(file_descriptor_proto, protobuf_name_to_package) {
+                (path_to_package, MessageOrEnum::Message(m)) => (path_to_package, m),
+                (_, MessageOrEnum::Enum(_)) => panic!("not a message"),
+            };
+
+        let mut field_proto_by_name = HashMap::new();
+        for field_proto in proto.get_field() {
+            field_proto_by_name.insert(field_proto.get_name(), field_proto);
+        }
+
+        let mut index_by_name = HashMap::new();
+        let mut index_by_number = HashMap::new();
+        for (i, f) in proto.get_field().iter().enumerate() {
+            index_by_number.insert(f.get_number() as u32, i);
+            index_by_name.insert(f.get_name().to_string(), i);
+        }
+
+        MessageDescriptor {
+            full_name: MessageDescriptor::compute_full_name(
+                file_descriptor_proto.get_package(),
+                &path_to_package,
+                &proto,
+            ),
+            proto,
+            factory,
+            fields: fields
+                .into_iter()
+                .map(|f| {
+                    let proto = *field_proto_by_name.get(&f.name_generic()).unwrap();
+                    FieldDescriptor::new(f, proto)
+                })
+                .collect(),
+            index_by_name,
+            index_by_number,
+        }
+    }
+
+    /// Construct a new message descriptor.
+    ///
+    /// This operation is called from generated code and rarely
+    /// need to be called directly.
+    #[doc(hidden)]
+    #[deprecated(
+        since = "2.12",
+        note = "Please regenerate .rs files from .proto files to use newer APIs"
+    )]
+    pub fn new<M: 'static + Message + Default + Clone + PartialEq>(
+        rust_name: &'static str,
+        fields: Vec<Box<FieldAccessor + 'static>>,
+        file: &'static FileDescriptorProto,
+    ) -> MessageDescriptor {
+        let factory = &MessageFactoryImpl(marker::PhantomData::<M>);
+        MessageDescriptor::new_non_generic_by_rust_name(rust_name, fields, file, factory)
+    }
+
+    /// Construct a new message descriptor.
+    ///
+    /// This operation is called from generated code and rarely
+    /// need to be called directly.
+    #[doc(hidden)]
+    pub fn new_pb_name<M: 'static + Message + Default + Clone + PartialEq>(
+        protobuf_name_to_package: &'static str,
+        fields: Vec<Box<FieldAccessor + 'static>>,
+        file_descriptor_proto: &'static FileDescriptorProto,
+    ) -> MessageDescriptor {
+        let factory = &MessageFactoryImpl(marker::PhantomData::<M>);
+        MessageDescriptor::new_non_generic_by_pb_name(
+            protobuf_name_to_package,
+            fields,
+            file_descriptor_proto,
+            factory,
+        )
+    }
+
+    /// New empty message
+    pub fn new_instance(&self) -> Box<dyn Message> {
+        self.factory.new_instance()
+    }
+
+    /// Protobuf message name
+    pub fn name(&self) -> &'static str {
+        self.proto.get_name()
+    }
+
+    /// Fully qualified protobuf message name
+    pub fn full_name(&self) -> &str {
+        &self.full_name[..]
+    }
+
+    /// Message field descriptors.
+    pub fn fields(&self) -> &[FieldDescriptor] {
+        &self.fields
+    }
+
+    /// Find field by name
+    pub fn field_by_name<'a>(&'a self, name: &str) -> &'a FieldDescriptor {
+        // TODO: clone is weird
+        let &index = self.index_by_name.get(&name.to_string()).unwrap();
+        &self.fields[index]
+    }
+
+    /// Find field by number
+    pub fn field_by_number<'a>(&'a self, number: u32) -> &'a FieldDescriptor {
+        let &index = self.index_by_number.get(&number).unwrap();
+        &self.fields[index]
+    }
+}
diff --git a/src/reflect/mod.rs b/src/reflect/mod.rs
new file mode 100644
index 0000000..ede3743
--- /dev/null
+++ b/src/reflect/mod.rs
@@ -0,0 +1,27 @@
+//! Reflection implementation for protobuf types.
+
+use core::Message;
+
+pub mod accessor;
+mod enums;
+mod field;
+mod find_message_or_enum;
+mod map;
+mod message;
+mod optional;
+mod repeated;
+mod value;
+
+pub use self::value::ProtobufValue;
+pub use self::value::ReflectValueRef;
+#[doc(hidden)]
+#[deprecated(since = "2.11", note = "Use ReflectValueRef instead")]
+pub use self::value::ReflectValueRef as ProtobufValueRef;
+
+pub use self::enums::EnumDescriptor;
+pub use self::enums::EnumValueDescriptor;
+
+pub use self::message::MessageDescriptor;
+
+pub use self::field::FieldDescriptor;
+pub use self::field::ReflectFieldRef;
diff --git a/src/reflect/optional.rs b/src/reflect/optional.rs
new file mode 100644
index 0000000..4d33752
--- /dev/null
+++ b/src/reflect/optional.rs
@@ -0,0 +1,50 @@
+use std::mem;
+
+use super::value::ProtobufValue;
+
+use singular::*;
+
+pub trait ReflectOptional: 'static {
+    fn to_option(&self) -> Option<&ProtobufValue>;
+
+    fn set_value(&mut self, value: &ProtobufValue);
+}
+
+impl<V: ProtobufValue + Clone + 'static> ReflectOptional for Option<V> {
+    fn to_option(&self) -> Option<&ProtobufValue> {
+        self.as_ref().map(|v| v as &ProtobufValue)
+    }
+
+    fn set_value(&mut self, value: &ProtobufValue) {
+        match value.as_any().downcast_ref::<V>() {
+            Some(v) => mem::replace(self, Some(v.clone())),
+            None => panic!(),
+        };
+    }
+}
+
+impl<V: ProtobufValue + Clone + 'static> ReflectOptional for SingularField<V> {
+    fn to_option(&self) -> Option<&ProtobufValue> {
+        self.as_ref().map(|v| v as &ProtobufValue)
+    }
+
+    fn set_value(&mut self, value: &ProtobufValue) {
+        match value.as_any().downcast_ref::<V>() {
+            Some(v) => mem::replace(self, SingularField::some(v.clone())),
+            None => panic!(),
+        };
+    }
+}
+
+impl<V: ProtobufValue + Clone + 'static> ReflectOptional for SingularPtrField<V> {
+    fn to_option(&self) -> Option<&ProtobufValue> {
+        self.as_ref().map(|v| v as &ProtobufValue)
+    }
+
+    fn set_value(&mut self, value: &ProtobufValue) {
+        match value.as_any().downcast_ref::<V>() {
+            Some(v) => mem::replace(self, SingularPtrField::some(v.clone())),
+            None => panic!(),
+        };
+    }
+}
diff --git a/src/reflect/repeated.rs b/src/reflect/repeated.rs
new file mode 100644
index 0000000..7ffc979
--- /dev/null
+++ b/src/reflect/repeated.rs
@@ -0,0 +1,192 @@
+use std::slice;
+
+use super::value::ProtobufValue;
+use super::value::ReflectValueRef;
+
+use repeated::RepeatedField;
+
+pub trait ReflectRepeated: 'static {
+    fn reflect_iter(&self) -> ReflectRepeatedIter;
+    fn len(&self) -> usize;
+    fn get(&self, index: usize) -> &ProtobufValue;
+}
+
+impl<V: ProtobufValue + 'static> ReflectRepeated for Vec<V> {
+    fn reflect_iter<'a>(&'a self) -> ReflectRepeatedIter<'a> {
+        ReflectRepeatedIter {
+            imp: Box::new(ReflectRepeatedIterImplSlice::<'a, V> { iter: self.iter() }),
+        }
+    }
+
+    fn len(&self) -> usize {
+        Vec::len(self)
+    }
+
+    fn get(&self, index: usize) -> &ProtobufValue {
+        &self[index]
+    }
+}
+
+// useless
+impl<V: ProtobufValue + 'static> ReflectRepeated for [V] {
+    fn reflect_iter<'a>(&'a self) -> ReflectRepeatedIter<'a> {
+        ReflectRepeatedIter {
+            imp: Box::new(ReflectRepeatedIterImplSlice::<'a, V> { iter: self.iter() }),
+        }
+    }
+
+    fn len(&self) -> usize {
+        <[_]>::len(self)
+    }
+
+    fn get(&self, index: usize) -> &ProtobufValue {
+        &self[index]
+    }
+}
+
+impl<V: ProtobufValue + 'static> ReflectRepeated for RepeatedField<V> {
+    fn reflect_iter<'a>(&'a self) -> ReflectRepeatedIter<'a> {
+        ReflectRepeatedIter {
+            imp: Box::new(ReflectRepeatedIterImplSlice::<'a, V> { iter: self.iter() }),
+        }
+    }
+
+    fn len(&self) -> usize {
+        RepeatedField::len(self)
+    }
+
+    fn get(&self, index: usize) -> &ProtobufValue {
+        &self[index]
+    }
+}
+
+trait ReflectRepeatedIterTrait<'a> {
+    fn next(&mut self) -> Option<&'a ProtobufValue>;
+}
+
+struct ReflectRepeatedIterImplSlice<'a, V: ProtobufValue + 'static> {
+    iter: slice::Iter<'a, V>,
+}
+
+impl<'a, V: ProtobufValue + 'static> ReflectRepeatedIterTrait<'a>
+    for ReflectRepeatedIterImplSlice<'a, V>
+{
+    fn next(&mut self) -> Option<&'a ProtobufValue> {
+        self.iter.next().map(|v| v as &ProtobufValue)
+    }
+}
+
+pub struct ReflectRepeatedIter<'a> {
+    imp: Box<ReflectRepeatedIterTrait<'a> + 'a>,
+}
+
+impl<'a> Iterator for ReflectRepeatedIter<'a> {
+    type Item = &'a ProtobufValue;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.imp.next()
+    }
+}
+
+impl<'a> IntoIterator for &'a ReflectRepeated {
+    type IntoIter = ReflectRepeatedIter<'a>;
+    type Item = &'a ProtobufValue;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.reflect_iter()
+    }
+}
+
+pub trait ReflectRepeatedEnum<'a> {
+    fn len(&self) -> usize;
+
+    fn get(&self, index: usize) -> ReflectValueRef<'a>;
+}
+
+pub trait ReflectRepeatedMessage<'a> {
+    fn len(&self) -> usize;
+
+    fn get(&self, index: usize) -> ReflectValueRef<'a>;
+}
+
+pub enum ReflectRepeatedRef<'a> {
+    Generic(&'a ReflectRepeated),
+    U32(&'a [u32]),
+    U64(&'a [u64]),
+    I32(&'a [i32]),
+    I64(&'a [i64]),
+    F32(&'a [f32]),
+    F64(&'a [f64]),
+    Bool(&'a [bool]),
+    String(&'a [String]),
+    Bytes(&'a [Vec<u8>]),
+    Enum(Box<ReflectRepeatedEnum<'a> + 'a>),
+    Message(Box<ReflectRepeatedMessage<'a> + 'a>),
+}
+
+impl<'a> ReflectRepeatedRef<'a> {
+    fn len(&self) -> usize {
+        match *self {
+            ReflectRepeatedRef::Generic(ref r) => r.len(),
+            ReflectRepeatedRef::U32(ref r) => r.len(),
+            ReflectRepeatedRef::U64(ref r) => r.len(),
+            ReflectRepeatedRef::I32(ref r) => r.len(),
+            ReflectRepeatedRef::I64(ref r) => r.len(),
+            ReflectRepeatedRef::F32(ref r) => r.len(),
+            ReflectRepeatedRef::F64(ref r) => r.len(),
+            ReflectRepeatedRef::Bool(ref r) => r.len(),
+            ReflectRepeatedRef::String(ref r) => r.len(),
+            ReflectRepeatedRef::Bytes(ref r) => r.len(),
+            ReflectRepeatedRef::Enum(ref r) => r.len(),
+            ReflectRepeatedRef::Message(ref r) => r.len(),
+        }
+    }
+
+    fn get(&self, index: usize) -> ReflectValueRef<'a> {
+        match *self {
+            ReflectRepeatedRef::Generic(ref r) => r.get(index).as_ref(),
+            ReflectRepeatedRef::U32(ref r) => ReflectValueRef::U32(r[index]),
+            ReflectRepeatedRef::U64(ref r) => ReflectValueRef::U64(r[index]),
+            ReflectRepeatedRef::I32(ref r) => ReflectValueRef::I32(r[index]),
+            ReflectRepeatedRef::I64(ref r) => ReflectValueRef::I64(r[index]),
+            ReflectRepeatedRef::F32(ref r) => ReflectValueRef::F32(r[index]),
+            ReflectRepeatedRef::F64(ref r) => ReflectValueRef::F64(r[index]),
+            ReflectRepeatedRef::Bool(ref r) => ReflectValueRef::Bool(r[index]),
+            ReflectRepeatedRef::String(ref r) => ReflectValueRef::String(&r[index]),
+            ReflectRepeatedRef::Bytes(ref r) => ReflectValueRef::Bytes(&r[index]),
+            ReflectRepeatedRef::Enum(ref r) => r.get(index),
+            ReflectRepeatedRef::Message(ref r) => r.get(index),
+        }
+    }
+}
+
+pub struct ReflectRepeatedRefIter<'a> {
+    repeated: &'a ReflectRepeatedRef<'a>,
+    pos: usize,
+}
+
+impl<'a> Iterator for ReflectRepeatedRefIter<'a> {
+    type Item = ReflectValueRef<'a>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.pos < self.repeated.len() {
+            let pos = self.pos;
+            self.pos += 1;
+            Some(self.repeated.get(pos))
+        } else {
+            None
+        }
+    }
+}
+
+impl<'a> IntoIterator for &'a ReflectRepeatedRef<'a> {
+    type IntoIter = ReflectRepeatedRefIter<'a>;
+    type Item = ReflectValueRef<'a>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        ReflectRepeatedRefIter {
+            repeated: self,
+            pos: 0,
+        }
+    }
+}
diff --git a/src/reflect/value.rs b/src/reflect/value.rs
new file mode 100644
index 0000000..22f76af
--- /dev/null
+++ b/src/reflect/value.rs
@@ -0,0 +1,185 @@
+use std::any::Any;
+
+#[cfg(feature = "bytes")]
+use bytes::Bytes;
+#[cfg(feature = "bytes")]
+use chars::Chars;
+
+use super::*;
+
+/// Type implemented by all protobuf elementary types
+/// (ints, floats, bool, string, bytes, enums, messages).
+pub trait ProtobufValue: Any + 'static {
+    /// As ref
+    fn as_ref(&self) -> ReflectValueRef;
+
+    /// Convert to `Any`
+    fn as_any(&self) -> &Any {
+        unimplemented!()
+    }
+
+    /// Is value non-zero?
+    fn is_non_zero(&self) -> bool {
+        self.as_ref().is_non_zero()
+    }
+
+    /// Return `ProtobufValueRef` if self is `Copy`.
+    ///
+    /// # Panics
+    ///
+    /// if `Self` is not `Copy`.
+    fn as_ref_copy(&self) -> ReflectValueRef<'static>
+//where Self : Copy // TODO
+    {
+        match self.as_ref() {
+            ReflectValueRef::Bool(v) => ReflectValueRef::Bool(v),
+            ReflectValueRef::U32(v) => ReflectValueRef::U32(v),
+            ReflectValueRef::U64(v) => ReflectValueRef::U64(v),
+            ReflectValueRef::I32(v) => ReflectValueRef::I32(v),
+            ReflectValueRef::I64(v) => ReflectValueRef::I64(v),
+            ReflectValueRef::F32(v) => ReflectValueRef::F32(v),
+            ReflectValueRef::F64(v) => ReflectValueRef::F64(v),
+            ReflectValueRef::Enum(v) => ReflectValueRef::Enum(v),
+            ReflectValueRef::String(..)
+            | ReflectValueRef::Bytes(..)
+            | ReflectValueRef::Message(..) => unreachable!(),
+        }
+    }
+}
+
+impl ProtobufValue for u32 {
+    fn as_ref(&self) -> ReflectValueRef {
+        ReflectValueRef::U32(*self)
+    }
+}
+
+impl ProtobufValue for u64 {
+    fn as_ref(&self) -> ReflectValueRef {
+        ReflectValueRef::U64(*self)
+    }
+}
+
+impl ProtobufValue for i32 {
+    fn as_ref(&self) -> ReflectValueRef {
+        ReflectValueRef::I32(*self)
+    }
+}
+
+impl ProtobufValue for i64 {
+    fn as_ref(&self) -> ReflectValueRef {
+        ReflectValueRef::I64(*self)
+    }
+}
+
+impl ProtobufValue for f32 {
+    fn as_ref(&self) -> ReflectValueRef {
+        ReflectValueRef::F32(*self)
+    }
+}
+
+impl ProtobufValue for f64 {
+    fn as_ref(&self) -> ReflectValueRef {
+        ReflectValueRef::F64(*self)
+    }
+}
+
+impl ProtobufValue for bool {
+    fn as_ref(&self) -> ReflectValueRef {
+        ReflectValueRef::Bool(*self)
+    }
+}
+
+impl ProtobufValue for String {
+    fn as_ref(&self) -> ReflectValueRef {
+        ReflectValueRef::String(*&self)
+    }
+}
+
+impl ProtobufValue for str {
+    fn as_ref(&self) -> ReflectValueRef {
+        ReflectValueRef::String(self)
+    }
+}
+
+impl ProtobufValue for Vec<u8> {
+    fn as_ref(&self) -> ReflectValueRef {
+        ReflectValueRef::Bytes(*&self)
+    }
+}
+
+#[cfg(feature = "bytes")]
+impl ProtobufValue for Bytes {
+    fn as_ref(&self) -> ReflectValueRef {
+        ReflectValueRef::Bytes(&*self)
+    }
+}
+
+#[cfg(feature = "bytes")]
+impl ProtobufValue for Chars {
+    fn as_ref(&self) -> ReflectValueRef {
+        ReflectValueRef::String(&*self)
+    }
+}
+
+// conflicting implementations, so generated code is used instead
+/*
+impl<E : ProtobufEnum> ProtobufValue for E {
+    fn as_ref(&self) -> ProtobufValueRef {
+        ProtobufValueRef::Enum(self.descriptor())
+    }
+}
+
+impl<M : Message> ProtobufValue for M {
+    fn as_ref(&self) -> ProtobufValueRef {
+        ProtobufValueRef::Message(self)
+    }
+}
+*/
+
+/// A reference to a value
+#[derive(Debug)]
+pub enum ReflectValueRef<'a> {
+    /// `u32`
+    U32(u32),
+    /// `u64`
+    U64(u64),
+    /// `i32`
+    I32(i32),
+    /// `i64`
+    I64(i64),
+    /// `f32`
+    F32(f32),
+    /// `f64`
+    F64(f64),
+    /// `bool`
+    Bool(bool),
+    /// `string`
+    String(&'a str),
+    /// `bytes`
+    Bytes(&'a [u8]),
+    /// `enum`
+    // TODO: change to (i32, EnumDescriptor)
+    Enum(&'static EnumValueDescriptor),
+    /// `message`
+    Message(&'a dyn Message),
+}
+
+impl<'a> ReflectValueRef<'a> {
+    /// Value is "non-zero"?
+    #[doc(hidden)]
+    pub fn is_non_zero(&self) -> bool {
+        match *self {
+            ReflectValueRef::U32(v) => v != 0,
+            ReflectValueRef::U64(v) => v != 0,
+            ReflectValueRef::I32(v) => v != 0,
+            ReflectValueRef::I64(v) => v != 0,
+            ReflectValueRef::F32(v) => v != 0.,
+            ReflectValueRef::F64(v) => v != 0.,
+            ReflectValueRef::Bool(v) => v,
+            ReflectValueRef::String(v) => !v.is_empty(),
+            ReflectValueRef::Bytes(v) => !v.is_empty(),
+            ReflectValueRef::Enum(v) => v.value() != 0,
+            ReflectValueRef::Message(_) => true,
+        }
+    }
+}