1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use super::super::util::*;
use super::{
    DataTypeBase, Field, FieldOrOneof, FieldOrOneofCase, Message, OneofField,
    ONEOF_FIELD_NUMBER_IN_MESSAGE_DESCRIPTOR,
};
use crate::Result;
use ::stable_puroro::protobuf::google::protobuf::{DescriptorProtoView, OneofDescriptorProtoView};
use ::std::fmt::Debug;
use ::std::rc::{Rc, Weak};

#[derive(Debug)]
pub(crate) struct Oneof {
    cache: AnonymousCache,
    message: Weak<Message>,
    oneof_index: usize,
    name: String,
    fields: Vec<Rc<OneofField>>,
}

impl Oneof {
    pub(crate) fn new(
        message_proto: &DescriptorProtoView,
        oneof_proto: &OneofDescriptorProtoView,
        oneof_index: usize,
        message: Weak<Message>,
    ) -> Rc<Oneof> {
        Rc::new_cyclic(|weak| {
            let fields = message_proto
                .field()
                .into_iter()
                .enumerate()
                .filter(|(_, f)| f.oneof_index() as usize == oneof_index)
                .map(|(i, f)| OneofField::new(f, Weak::clone(weak), i))
                .collect::<Vec<_>>();
            Oneof {
                cache: Default::default(),
                message,
                oneof_index,
                name: oneof_proto.name().to_string(),
                fields,
            }
        })
    }
}

impl DataTypeBase for Oneof {
    fn cache(&self) -> &AnonymousCache {
        &self.cache
    }
    fn name(&self) -> Result<&str> {
        Ok(&self.name)
    }
}

impl FieldOrOneof for Oneof {
    fn either(&self) -> FieldOrOneofCase<&Field, &Oneof> {
        FieldOrOneofCase::Oneof(self)
    }
}

impl Oneof {
    pub(crate) fn fields(&self) -> Result<impl Iterator<Item = &Rc<OneofField>>> {
        Ok(Box::new(self.fields.iter()))
    }
    pub(crate) fn message(&self) -> Result<Rc<Message>> {
        Ok(self.message.try_upgrade()?)
    }
    pub(crate) fn location_path(&self) -> Result<impl Iterator<Item = i32>> {
        let this_path = [
            ONEOF_FIELD_NUMBER_IN_MESSAGE_DESCRIPTOR,
            self.oneof_index.try_into()?,
        ];
        Ok(self
            .message()?
            .location_path()?
            .chain(this_path.into_iter()))
    }
}