(&mut self, tape: &Tape<'_>, pos: &[u32])
| 121 | |
| 122 | impl ArrayDecoder for StructArrayDecoder { |
| 123 | fn decode(&mut self, tape: &Tape<'_>, pos: &[u32]) -> Result<ArrayRef, ArrowError> { |
| 124 | let fields = struct_fields(&self.data_type); |
| 125 | let row_count = pos.len(); |
| 126 | let field_count = fields.len(); |
| 127 | self.field_tape_positions.resize(field_count, row_count)?; |
| 128 | let mut nulls = self.is_nullable.then(|| NullBufferBuilder::new(pos.len())); |
| 129 | |
| 130 | { |
| 131 | // We avoid having the match on self.struct_mode inside the hot loop for performance |
| 132 | // TODO: Investigate how to extract duplicated logic. |
| 133 | match self.struct_mode { |
| 134 | StructMode::ObjectOnly => { |
| 135 | for (row, p) in pos.iter().enumerate() { |
| 136 | let end_idx = match (tape.get(*p), nulls.as_mut()) { |
| 137 | (TapeElement::StartObject(end_idx), None) => end_idx, |
| 138 | (TapeElement::StartObject(end_idx), Some(nulls)) => { |
| 139 | nulls.append_non_null(); |
| 140 | end_idx |
| 141 | } |
| 142 | (TapeElement::Null, Some(nulls)) => { |
| 143 | nulls.append_null(); |
| 144 | continue; |
| 145 | } |
| 146 | (_, Some(nulls)) if self.ignore_type_conflicts => { |
| 147 | nulls.append_null(); |
| 148 | continue; |
| 149 | } |
| 150 | (_, _) => return Err(tape.error(*p, "{")), |
| 151 | }; |
| 152 | |
| 153 | let mut cur_idx = *p + 1; |
| 154 | while cur_idx < end_idx { |
| 155 | // Read field name |
| 156 | let field_name = match tape.get(cur_idx) { |
| 157 | TapeElement::String(s) => tape.get_string(s), |
| 158 | _ => return Err(tape.error(cur_idx, "field name")), |
| 159 | }; |
| 160 | |
| 161 | // Update child pos if match found |
| 162 | let field_idx = match &self.field_name_to_index { |
| 163 | Some(map) => map.get(field_name).copied(), |
| 164 | None => fields.iter().position(|x| x.name() == field_name), |
| 165 | }; |
| 166 | match field_idx { |
| 167 | Some(field_idx) => { |
| 168 | self.field_tape_positions.set(field_idx, row, cur_idx + 1); |
| 169 | } |
| 170 | None => { |
| 171 | if self.strict_mode { |
| 172 | return Err(ArrowError::JsonError(format!( |
| 173 | "column '{field_name}' missing from schema", |
| 174 | ))); |
| 175 | } |
| 176 | } |
| 177 | } |
| 178 | // Advance to next field |
| 179 | cur_idx = tape.next(cur_idx + 1, "field value")?; |
| 180 | } |
nothing calls this directly
no test coverage detected