| 120 | } |
| 121 | |
| 122 | fn format_internal( |
| 123 | vm: &VirtualMachine, |
| 124 | format: &FormatString, |
| 125 | field_func: &mut impl FnMut(FieldType) -> PyResult, |
| 126 | ) -> PyResult<Wtf8Buf> { |
| 127 | let mut final_string = Wtf8Buf::new(); |
| 128 | for part in &format.format_parts { |
| 129 | let pystr; |
| 130 | let result_string: &Wtf8 = match part { |
| 131 | FormatPart::Field { |
| 132 | field_name, |
| 133 | conversion_spec, |
| 134 | format_spec, |
| 135 | } => { |
| 136 | let FieldName { field_type, parts } = |
| 137 | FieldName::parse(field_name).map_err(|e| e.to_pyexception(vm))?; |
| 138 | |
| 139 | let mut argument = field_func(field_type)?; |
| 140 | |
| 141 | for name_part in parts { |
| 142 | match name_part { |
| 143 | FieldNamePart::Attribute(attribute) => { |
| 144 | argument = argument.get_attr(&vm.ctx.new_str(attribute), vm)?; |
| 145 | } |
| 146 | FieldNamePart::Index(index) => { |
| 147 | argument = argument.get_item(&index, vm)?; |
| 148 | } |
| 149 | FieldNamePart::StringIndex(index) => { |
| 150 | argument = argument.get_item(&index, vm)?; |
| 151 | } |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | let nested_format = |
| 156 | FormatString::from_str(format_spec).map_err(|e| e.to_pyexception(vm))?; |
| 157 | let format_spec = format_internal(vm, &nested_format, field_func)?; |
| 158 | |
| 159 | let argument = match conversion_spec.and_then(FormatConversion::from_char) { |
| 160 | Some(FormatConversion::Str) => argument.str(vm)?.into(), |
| 161 | Some(FormatConversion::Repr) => argument.repr(vm)?.into(), |
| 162 | Some(FormatConversion::Ascii) => builtins::ascii(argument, vm)?.into(), |
| 163 | Some(FormatConversion::Bytes) => { |
| 164 | vm.call_method(&argument, identifier!(vm, decode).as_str(), ())? |
| 165 | } |
| 166 | None => argument, |
| 167 | }; |
| 168 | |
| 169 | // FIXME: compiler can intern specs using parser tree. Then this call can be interned_str |
| 170 | pystr = vm.format(&argument, vm.ctx.new_str(format_spec))?; |
| 171 | pystr.as_wtf8() |
| 172 | } |
| 173 | FormatPart::Literal(literal) => literal, |
| 174 | }; |
| 175 | final_string.push_wtf8(result_string); |
| 176 | } |
| 177 | Ok(final_string) |
| 178 | } |
| 179 | |