This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch main
in repository ego.

View the commit online.

commit bc1c35f31e299c9d854670b1cffe0e58129aa36f
Author: [email protected] <[email protected]>
AuthorDate: Tue Mar 31 09:08:47 2026 -0600

    feat(ego-gen): add Eina_Slice property setter support
    
    Generate []byte setters for properties taking Eina_Slice or
    Eina_Rw_Slice by value. C wrapper constructs the slice struct
    from pointer + length. Unblocks line_delimiter, input_panel_imdata,
    and ip_address setters.
    
    Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---
 cmd/ego-gen/generator.go            |  1 +
 cmd/ego-gen/generator_test.go       | 58 +++++++++++++++++++++++++++++++++++++
 cmd/ego-gen/main.go                 | 35 +++++++++++++---------
 cmd/ego-gen/templates/class.go.tmpl | 19 +++++++++++-
 efl/input_text/entity.go            | 16 ++++++++++
 efl/io/buffered_stream.go           | 16 ++++++++++
 efl/io/copier.go                    | 16 ++++++++++
 efl/net/ip_address.go               | 16 ++++++++++
 efl/ui/textbox.go                   | 16 ++++++++++
 9 files changed, 178 insertions(+), 15 deletions(-)

diff --git a/cmd/ego-gen/generator.go b/cmd/ego-gen/generator.go
index 610645b..44b646e 100644
--- a/cmd/ego-gen/generator.go
+++ b/cmd/ego-gen/generator.go
@@ -103,6 +103,7 @@ type PropertyData struct {
 	HasSet            bool
 	IsEo              bool     // true when the value type is an Eo class reference
 	IsStruct          bool     // true when the value type is a known struct (e.g. Eina_Size2D)
+	IsSlice           bool     // true when the value type is Eina_Slice or Eina_Rw_Slice ([]byte)
 	StructGoType      string   // e.g. "efl.Size2D"
 	StructCType       string   // e.g. "Eina_Size2D"
 	StructGoFields    []string // e.g. ["W", "H"]
diff --git a/cmd/ego-gen/generator_test.go b/cmd/ego-gen/generator_test.go
index 9182629..9ba4014 100644
--- a/cmd/ego-gen/generator_test.go
+++ b/cmd/ego-gen/generator_test.go
@@ -1224,3 +1224,61 @@ func TestGenerateClass_CallbackMethod(t *testing.T) {
 		}
 	}
 }
+
+func TestGenerateClass_SliceSetter(t *testing.T) {
+	g, outDir := newTestGenerator(t)
+
+	si := GetStructInfo("Eina_Slice")
+	data := ClassData{
+		PackageName:   "io",
+		GoName:        "Copier",
+		EolianName:    "Efl.Io.Copier",
+		CClassName:    "EFL_IO_COPIER_CLASS",
+		CClassGetFunc: "efl_io_copier_class_get",
+		CPrefix:       "efl_io_copier",
+		EOHeaderFile:  "efl_io_copier.eo.h",
+		Properties: []PropertyData{
+			{
+				GoGetter:          "LineDelimiter",
+				GoSetter:          "SetLineDelimiter",
+				CGetName:          "efl_io_copier_line_delimiter_get",
+				CSetName:          "efl_io_copier_line_delimiter_set",
+				GoType:            "[]byte",
+				CType:             "Eina_Slice",
+				HasGet:            false,
+				HasSet:            true,
+				IsStruct:          false,
+				IsSlice:           true,
+				StructGoType:      si.GoType,
+				StructCType:       si.CType,
+				StructGoFields:    si.GoFields,
+				StructCFields:     si.CFields,
+				StructCFieldTypes: si.CFieldTypes,
+			},
+		},
+	}
+
+	if err := g.GenerateClass(data); err != nil {
+		t.Fatalf("GenerateClass: %v", err)
+	}
+
+	outFile := filepath.Join(outDir, "io", "copier.go")
+	content, err := os.ReadFile(outFile)
+	if err != nil {
+		t.Fatalf("output file not found at %s: %v", outFile, err)
+	}
+
+	src := string(content)
+
+	mustContain := []string{
+		"_ego_set_struct_efl_io_copier_line_delimiter_set",
+		"func (o *Copier) SetLineDelimiter(val []byte)",
+		"Eina_Slice",
+	}
+
+	for _, want := range mustContain {
+		if !strings.Contains(src, want) {
+			t.Errorf("output missing expected pattern %q\nfile content:\n%s", want, src)
+		}
+	}
+}
diff --git a/cmd/ego-gen/main.go b/cmd/ego-gen/main.go
index 42d9761..782812d 100644
--- a/cmd/ego-gen/main.go
+++ b/cmd/ego-gen/main.go
@@ -87,10 +87,8 @@ var methodBlocklist = map[string]bool{
 	// now handled via known struct support.
 	// efl.Ui.ImageZoomable — image_region setter now handled via known struct support.
 	// efl.Ui.Win — hint_base/hint_step now handled via known struct support.
-	// efl.Net.IpAddress — address setter takes Eina_Slice struct by value
-	"efl_net_ip_address_set": true,
-	// efl.Io.BufferedStream — line_delimiter setter takes Eina_Slice by value
-	"efl_io_buffered_stream_line_delimiter_set": true,
+	// efl.Net.IpAddress — address setter now handled via slice property support.
+	// efl.Io.BufferedStream — line_delimiter setter now handled via slice property support.
 	// efl.Ui.Calendar — date setters take Efl_Time (struct tm) by value
 	"efl_ui_calendar_date_min_set": true,
 	"efl_ui_calendar_date_max_set": true,
@@ -190,8 +188,7 @@ var methodBlocklist = map[string]bool{
 	// efl.Ui.Widget — focus_state_apply takes struct by value; theme_apply returns Eina_Error
 	"efl_ui_widget_focus_state_apply": true,
 	"efl_ui_widget_theme_apply":       true,
-	// efl.Io.Copier — line_delimiter takes Eina_Slice by value (struct parameter)
-	"efl_io_copier_line_delimiter_set": true,
+	// efl.Io.Copier — line_delimiter setter now handled via slice property support.
 	// efl.Io — methods returning Eina_Error (integer, not pointer) or taking Eina_*_Slice out-params
 	"efl_io_closer_close":    true,
 	"efl_io_positioner_seek": true,
@@ -201,8 +198,7 @@ var methodBlocklist = map[string]bool{
 	// efl.Canvas.GestureRecognizer — returns enum (not a pointer) through pointer path
 	"efl_gesture_recognizer_recognize": true,
 	// efl.Canvas.Gesture — hotspot setter now handled via known struct support.
-	// efl.Input_Text — imdata setter takes Eina_Slice struct by value
-	"efl_input_text_input_panel_imdata_set": true,
+	// efl.Input_Text — imdata setter now handled via slice property support.
 	// efl.Canvas.Scene — pointer_position has extra out-param
 	"efl_canvas_scene_pointer_position_get": true,
 	// efl.Canvas.Textgrid — multiple out-params for palette colors
@@ -1067,6 +1063,7 @@ func buildPropertyData(f *Function, cPrefix string) (PropertyData, error) {
 	var cType, goType string
 	var isEo bool
 	var isStruct bool
+	var isSlice bool
 	if rt := f.ReturnType(FunctionPropGet); rt != nil {
 		cType = rt.CType()
 		goType = CTypeToGo(cType)
@@ -1076,8 +1073,10 @@ func buildPropertyData(f *Function, cPrefix string) (PropertyData, error) {
 		} else if si != nil && si.IsSlice {
 			// Eina_Slice / Eina_Rw_Slice: the property getter returns a slice
 			// struct whose fields include "const void *", which cannot be used
-			// as a cgo variable type. Disable the getter for such properties.
+			// as a cgo variable type. Disable the getter; mark as slice setter.
 			hasGet = false
+			isSlice = true
+			goType = si.GoType
 		}
 	} else if getVals := f.PropertyValues(FunctionPropGet); len(getVals) == 1 {
 		// Single getter value parameter — the C getter returns this type
@@ -1090,10 +1089,11 @@ func buildPropertyData(f *Function, cPrefix string) (PropertyData, error) {
 				cType = ct
 				goType = CTypeToGo(ct)
 			} else if si != nil && si.IsSlice {
-				// Eina_Slice / Eina_Rw_Slice: disable getter (see above).
+				// Eina_Slice / Eina_Rw_Slice: disable getter; mark as slice setter.
 				hasGet = false
+				isSlice = true
 				cType = ct
-				goType = CTypeToGo(ct)
+				goType = si.GoType
 			} else if IsStructType(ct) {
 				// Unknown struct: cannot be cast through uintptr_t.
 				// Disable the getter.
@@ -1115,8 +1115,14 @@ func buildPropertyData(f *Function, cPrefix string) (PropertyData, error) {
 				cType = pt.CType()
 				goType = CTypeToGo(cType)
 				isEo = pt.IsClass()
-				if si := GetStructInfo(cType); si != nil && !si.IsSlice {
-					isStruct = true
+				if si := GetStructInfo(cType); si != nil {
+					if si.IsSlice {
+						// Eina_Slice / Eina_Rw_Slice setter: treat as slice property.
+						isSlice = true
+						goType = si.GoType
+					} else {
+						isStruct = true
+					}
 				}
 			}
 		}
@@ -1139,9 +1145,10 @@ func buildPropertyData(f *Function, cPrefix string) (PropertyData, error) {
 		HasSet:   hasSet,
 		IsEo:     isEo,
 		IsStruct: isStruct,
+		IsSlice:  isSlice,
 	}
 
-	if isStruct {
+	if isStruct || isSlice {
 		si := GetStructInfo(cType)
 		pd.GoType = si.GoType
 		pd.StructGoType = si.GoType
diff --git a/cmd/ego-gen/templates/class.go.tmpl b/cmd/ego-gen/templates/class.go.tmpl
index f773821..feba194 100644
--- a/cmd/ego-gen/templates/class.go.tmpl
+++ b/cmd/ego-gen/templates/class.go.tmpl
@@ -170,6 +170,15 @@ static void _ego_set_struct_{{$prop.CSetName}}(Eo *obj{{range $i, $f := $prop.St
 }
 {{- end}}
 {{- end}}
+{{- if $prop.IsSlice}}
+{{- if $prop.HasSet}}
+// _ego_set_struct_{{$prop.CSetName}} wraps the setter, constructing the slice
+// struct from mem pointer and len parameters.
+static void _ego_set_struct_{{$prop.CSetName}}(Eo *obj, {{index $prop.StructCFieldTypes 0}} mem, size_t len) {
+    {{$prop.CSetName}}(obj, ({{$prop.StructCType}}){ .len = len, .mem = mem });
+}
+{{- end}}
+{{- end}}
 {{- end}}
 {{- range $ctor := .Constructors}}
 {{- if $ctor.IsStruct}}
@@ -415,7 +424,15 @@ func (o *{{$.GoName}}) {{$prop.GoSetter}}({{range $i, $v := $prop.MultiSetValues
 {{- else}}
 // {{$prop.GoSetter}} sets the {{$prop.GoGetter}} property of the {{$.GoName}}.
 func (o *{{$.GoName}}) {{$prop.GoSetter}}(val {{if $prop.IsEo}}efl.Objecter{{else}}{{$prop.GoType}}{{end}}) {
-{{- if $prop.IsStruct}}
+{{- if $prop.IsSlice}}
+    var cMem unsafe.Pointer
+    var cLen C.size_t
+    if len(val) > 0 {
+        cMem = unsafe.Pointer(&val[0])
+        cLen = C.size_t(len(val))
+    }
+    C._ego_set_struct_{{$prop.CSetName}}((*C.Eo)(o.Eo()), cMem, cLen)
+{{- else if $prop.IsStruct}}
     C._ego_set_struct_{{$prop.CSetName}}((*C.Eo)(o.Eo()){{range $i, $gf := $prop.StructGoFields}}, C.{{index $prop.StructCFieldTypes $i}}(val.{{$gf}}){{end}})
 {{- else if $prop.IsEo}}
     C.{{$prop.CSetName}}((*C.Eo)(o.Eo()), (*C.Eo)(val.Eo()))
diff --git a/efl/input_text/entity.go b/efl/input_text/entity.go
index 1572f56..db17427 100644
--- a/efl/input_text/entity.go
+++ b/efl/input_text/entity.go
@@ -162,6 +162,11 @@ static void _ego_set_efl_input_text_input_panel_return_key_state_set(Eo *obj, vo
         (__typeof__(efl_input_text_input_panel_return_key_state_get((const Eo *)0)))(uintptr_t)val;
     efl_input_text_input_panel_return_key_state_set(obj, typed);
 }
+// _ego_set_struct_efl_input_text_input_panel_imdata_set wraps the setter, constructing the slice
+// struct from mem pointer and len parameters.
+static void _ego_set_struct_efl_input_text_input_panel_imdata_set(Eo *obj, const void * mem, size_t len) {
+    efl_input_text_input_panel_imdata_set(obj, (Eina_Slice){ .len = len, .mem = mem });
+}
 */
 import "C"
 
@@ -299,6 +304,17 @@ func (o *Entity) SetInputPanelReturnKeyState(val unsafe.Pointer) {
 	C._ego_set_efl_input_text_input_panel_return_key_state_set((*C.Eo)(o.Eo()), val)
 }
 
+// SetInputPanelImdata sets the InputPanelImdata property of the Entity.
+func (o *Entity) SetInputPanelImdata(val []byte) {
+	var cMem unsafe.Pointer
+	var cLen C.size_t
+	if len(val) > 0 {
+		cMem = unsafe.Pointer(&val[0])
+		cLen = C.size_t(len(val))
+	}
+	C._ego_set_struct_efl_input_text_input_panel_imdata_set((*C.Eo)(o.Eo()), cMem, cLen)
+}
+
 // InputPanelShow calls the efl_input_text_input_panel_show method on Entity.
 func (o *Entity) InputPanelShow() {
 	C.efl_input_text_input_panel_show((*C.Eo)(o.Eo()))
diff --git a/efl/io/buffered_stream.go b/efl/io/buffered_stream.go
index 7ce32da..3be9074 100644
--- a/efl/io/buffered_stream.go
+++ b/efl/io/buffered_stream.go
@@ -106,6 +106,11 @@ static void _ego_set_efl_io_buffered_stream_inner_io_set(Eo *obj, void *val) {
         (__typeof__(efl_io_buffered_stream_inner_io_get((const Eo *)0)))(uintptr_t)val;
     efl_io_buffered_stream_inner_io_set(obj, typed);
 }
+// _ego_set_struct_efl_io_buffered_stream_line_delimiter_set wraps the setter, constructing the slice
+// struct from mem pointer and len parameters.
+static void _ego_set_struct_efl_io_buffered_stream_line_delimiter_set(Eo *obj, const void * mem, size_t len) {
+    efl_io_buffered_stream_line_delimiter_set(obj, (Eina_Slice){ .len = len, .mem = mem });
+}
 // _ego_ev_EFL_IO_BUFFERED_STREAM_EVENT_WRITE_FINISHED returns the event description pointer using the EFL
 // macro, avoiding a conflicting extern declaration for the symbol name.
 static const Efl_Event_Description *_ego_ev_EFL_IO_BUFFERED_STREAM_EVENT_WRITE_FINISHED(void) {
@@ -244,6 +249,17 @@ func (o *BufferedStream) SetMaxQueueSizeOutput(val uint) {
 	C.efl_io_buffered_stream_max_queue_size_output_set((*C.Eo)(o.Eo()), C.size_t(val))
 }
 
+// SetLineDelimiter sets the LineDelimiter property of the BufferedStream.
+func (o *BufferedStream) SetLineDelimiter(val []byte) {
+	var cMem unsafe.Pointer
+	var cLen C.size_t
+	if len(val) > 0 {
+		cMem = unsafe.Pointer(&val[0])
+		cLen = C.size_t(len(val))
+	}
+	C._ego_set_struct_efl_io_buffered_stream_line_delimiter_set((*C.Eo)(o.Eo()), cMem, cLen)
+}
+
 // TimeoutInactivity returns the TimeoutInactivity property of the BufferedStream.
 func (o *BufferedStream) TimeoutInactivity() float64 {
 	return float64(C.efl_io_buffered_stream_timeout_inactivity_get((*C.Eo)(o.Eo())))
diff --git a/efl/io/copier.go b/efl/io/copier.go
index a33498a..260fc07 100644
--- a/efl/io/copier.go
+++ b/efl/io/copier.go
@@ -113,6 +113,11 @@ static void _ego_set_efl_io_copier_destination_set(Eo *obj, void *val) {
         (__typeof__(efl_io_copier_destination_get((const Eo *)0)))(uintptr_t)val;
     efl_io_copier_destination_set(obj, typed);
 }
+// _ego_set_struct_efl_io_copier_line_delimiter_set wraps the setter, constructing the slice
+// struct from mem pointer and len parameters.
+static void _ego_set_struct_efl_io_copier_line_delimiter_set(Eo *obj, const void * mem, size_t len) {
+    efl_io_copier_line_delimiter_set(obj, (Eina_Slice){ .len = len, .mem = mem });
+}
 // _ego_ev_EFL_IO_COPIER_EVENT_DONE returns the event description pointer using the EFL
 // macro, avoiding a conflicting extern declaration for the symbol name.
 static const Efl_Event_Description *_ego_ev_EFL_IO_COPIER_EVENT_DONE(void) {
@@ -216,6 +221,17 @@ func (o *Copier) SetDestination(val efl.Objecter) {
 	C.efl_io_copier_destination_set((*C.Eo)(o.Eo()), (*C.Eo)(val.Eo()))
 }
 
+// SetLineDelimiter sets the LineDelimiter property of the Copier.
+func (o *Copier) SetLineDelimiter(val []byte) {
+	var cMem unsafe.Pointer
+	var cLen C.size_t
+	if len(val) > 0 {
+		cMem = unsafe.Pointer(&val[0])
+		cLen = C.size_t(len(val))
+	}
+	C._ego_set_struct_efl_io_copier_line_delimiter_set((*C.Eo)(o.Eo()), cMem, cLen)
+}
+
 // BufferLimit returns the BufferLimit property of the Copier.
 func (o *Copier) BufferLimit() uint {
 	return uint(C.efl_io_copier_buffer_limit_get((*C.Eo)(o.Eo())))
diff --git a/efl/net/ip_address.go b/efl/net/ip_address.go
index 8b43935..6326cae 100644
--- a/efl/net/ip_address.go
+++ b/efl/net/ip_address.go
@@ -110,6 +110,11 @@ static void _ego_set_efl_net_ip_address_sockaddr_set(Eo *obj, void *val) {
         (__typeof__(efl_net_ip_address_sockaddr_get((const Eo *)0)))(uintptr_t)val;
     efl_net_ip_address_sockaddr_set(obj, typed);
 }
+// _ego_set_struct_efl_net_ip_address_set wraps the setter, constructing the slice
+// struct from mem pointer and len parameters.
+static void _ego_set_struct_efl_net_ip_address_set(Eo *obj, const void * mem, size_t len) {
+    efl_net_ip_address_set(obj, (Eina_Slice){ .len = len, .mem = mem });
+}
 */
 import "C"
 
@@ -189,6 +194,17 @@ func (o *IpAddress) SetPort(val unsafe.Pointer) {
 	C._ego_set_efl_net_ip_address_port_set((*C.Eo)(o.Eo()), val)
 }
 
+// SetAddress sets the Address property of the IpAddress.
+func (o *IpAddress) SetAddress(val []byte) {
+	var cMem unsafe.Pointer
+	var cLen C.size_t
+	if len(val) > 0 {
+		cMem = unsafe.Pointer(&val[0])
+		cLen = C.size_t(len(val))
+	}
+	C._ego_set_struct_efl_net_ip_address_set((*C.Eo)(o.Eo()), cMem, cLen)
+}
+
 // Sockaddr returns the Sockaddr property of the IpAddress.
 func (o *IpAddress) Sockaddr() unsafe.Pointer {
 	return unsafe.Pointer(C._ego_get_efl_net_ip_address_sockaddr_get((*C.Eo)(o.Eo())))
diff --git a/efl/ui/textbox.go b/efl/ui/textbox.go
index d6d9708..edce364 100644
--- a/efl/ui/textbox.go
+++ b/efl/ui/textbox.go
@@ -427,6 +427,11 @@ static void _ego_get_struct_efl_ui_scrollable_step_size_get(const Eo *obj, int *
 static void _ego_set_struct_efl_ui_scrollable_step_size_set(Eo *obj, int x, int y) {
     efl_ui_scrollable_step_size_set(obj, (Eina_Position2D){ .x = x, .y = y });
 }
+// _ego_set_struct_efl_input_text_input_panel_imdata_set wraps the setter, constructing the slice
+// struct from mem pointer and len parameters.
+static void _ego_set_struct_efl_input_text_input_panel_imdata_set(Eo *obj, const void * mem, size_t len) {
+    efl_input_text_input_panel_imdata_set(obj, (Eina_Slice){ .len = len, .mem = mem });
+}
 // _ego_ev_EFL_UI_TEXTBOX_EVENT_SELECTION_PASTE returns the event description pointer using the EFL
 // macro, avoiding a conflicting extern declaration for the symbol name.
 static const Efl_Event_Description *_ego_ev_EFL_UI_TEXTBOX_EVENT_SELECTION_PASTE(void) {
@@ -999,6 +1004,17 @@ func (o *Textbox) SetInputPanelReturnKeyState(val unsafe.Pointer) {
 	C._ego_set_efl_input_text_input_panel_return_key_state_set((*C.Eo)(o.Eo()), val)
 }
 
+// SetInputPanelImdata sets the InputPanelImdata property of the Textbox.
+func (o *Textbox) SetInputPanelImdata(val []byte) {
+	var cMem unsafe.Pointer
+	var cLen C.size_t
+	if len(val) > 0 {
+		cMem = unsafe.Pointer(&val[0])
+		cLen = C.size_t(len(val))
+	}
+	C._ego_set_struct_efl_input_text_input_panel_imdata_set((*C.Eo)(o.Eo()), cMem, cLen)
+}
+
 // Text returns the Text property of the Textbox.
 func (o *Textbox) Text() string {
 	cResult := C.efl_text_get((*C.Eo)(o.Eo()))

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to