package OpenAIAsync::Types; use v5.36.0; use Object::Pad; use Object::PadX::Role::AutoMarshal; use Object::PadX::Role::AutoJSON; use Object::Pad::ClassAttr::Struct; # Base role for all the types to simplify things later role OpenAIAsync::Types::Base :does(Object::PadX::Role::AutoJSON) :does(Object::PadX::Role::AutoMarshal) :Struct { use JSON::MaybeXS qw//; our $_json = JSON::MaybeXS->new(utf8 => 1, convert_blessed => 1); method _encode() { return $_json->encode($self); } } # Keep the JSON role stuff here, I might use it to annotate encodings of some non-json fields? not sure role OpenAIAsync::Types::BaseFormEncoding :does(Object::PadX::Role::AutoJSON) :does(Object::PadX::Role::AutoMarshal) :Struct { use WWW:Form::UrlEncoded; use Object::Pad::MOP::FieldAttr; use Object::Pad::MOP::Field; use Object::Pad::MOP::Class; my $_to_str = sub ($x) { return "".$x; }; my $_to_num = sub ($x) { return 0+$x; }; my $_to_bool = sub ($x) { return !!$x ? \1 : \0; }; my $_to_list = sub ($ref, $type) { my $sub = $type eq 'JSONNum' ? $_to_num : $type eq 'JSONStr' ? $_to_str : $type eq 'JSONBool' ? $_to_bool : sub {die "Wrong type $type in json conversion"}; return [map {$sub->($_)} $ref->@*] }; method _as_hash() { my $class = __CLASS__; my $classmeta = Object::Pad::MOP::Class->for_class($class); my @metafields = $classmeta->fields; my %json_out = (); for my $metafield (@metafields) { my $field_name = $metafield->name; my $sigil = $metafield->sigil; my $has_exclude = $metafield->has_attribute("JSONExclude"); next if $has_exclude; next if $sigil ne '$'; # Don't try to handle anything but scalars my $has_null = $metafield->has_attribute("JSONNull"); my $value = $metafield->value($self); next unless (defined $value || $has_null); my $key = $field_name =~ s/^\$//r; $key = $metafield->get_attribute_value("JSONKey") if $metafield->has_attribute("JSONKey"); if ($metafield->has_attribute('JSONBool')) { $value = $_to_bool->($value); } elsif ($metafield->has_attribute('JSONNum')) { # Force numification $value = $_to_num->($value); } elsif ($metafield->has_attribute('JSONList')) { my $type = $metafield->get_attribute_value('JSONList'); $value = $_to_list->($value, $type); } else { # Force stringification $value = $_to_str->($value); } $json_out{$key} = $value; } } return \%json_out; method _encode() { my $hash = $self->_as_hash(); my $string = WWW::Form::UrlEncoded::build_urlencoded($hash); return $string; } }