ronantakizawa/codereview-bench huggingface dataset:
Repository: fyne-io/fyne
File: container/navigation.go (Go)

Code before:
	if nav.level > 1 {
		objs[nav.level-2].Show()
	}

	nav.level--
	nav.Refresh()

	return objs[nav.level]
}

// Forward shows the next object in the stack again.
//
// Since: 2.7
func (nav *Navigation) Forward() fyne.CanvasObject {
	if nav.level >= len(nav.stack.Objects) {
		return nil
	}

	nav.stack.Objects[nav.level-1].Hide()
	nav.stack.Objects[nav.level].Show()
	nav.level++

	return nav.stack.Objects[nav.level-1]
}

// SetTitle changes the navigation title and the title for the current object.
//
// Since: 2.7
func (nav *Navigation) SetTitle(s string) {
	nav.titles[nav.level] = s
}

func (nav *Navigation) setup() {
	objs := []fyne.CanvasObject{}
	titles := []string{}
	if nav.Root != nil {
		objs = append(objs, nav.Root)
		titles = append(titles, nav.Title)
	}
	nav.level = len(objs)
	nav.stack.Layout = layout.NewStackLayout()
	nav.stack.Objects = objs
	nav.titles = titles
	nav.ExtendBaseWidget(nav)
}

var _ fyne.WidgetRenderer = (*navigatorRenderer)(nil)

type navigatorRenderer struct {
	nav    *Navigation
	back   widget.Button

Review comment (suggestion):
This function makes me a little nervous - what it does varies with what the current level is but the field `Title` does not vary... 

I think for consistency this should be setting the root title. Perhaps another method that more clearly indicates it is setting the title of a level.

Code after:

	nav.level--
	nav.Refresh()

	return objs[nav.level]
}

// Forward shows the next object in the stack again.
//
// Since: 2.7
func (nav *Navigation) Forward() fyne.CanvasObject {
	if nav.level >= len(nav.stack.Objects) {
		return nil
	}

	nav.stack.Objects[nav.level-1].Hide()
	nav.stack.Objects[nav.level].Show()
	nav.level++

	return nav.stack.Objects[nav.level-1]
}

// SetTitle changes the root navigation title shown by default.
//
// Since: 2.7
func (nav *Navigation) SetTitle(s string) {
	nav.Title = s
	nav.Refresh()
}

// SetCurrentTitle changes the navigation title for the current level.
//
// Since: 2.7
func (nav *Navigation) SetCurrentTitle(s string) {
	if nav.level > 1 && nav.level-1 < len(nav.titles) {
		nav.titles[nav.level-1] = s
		nav.Refresh()
	}
}

func (nav *Navigation) setup() {
	objs := []fyne.CanvasObject{}
	titles := []string{}
	if nav.Root != nil {
		objs = append(objs, nav.Root)
		titles = append(titles, nav.Title)
	}
	nav.level = len(objs)
	nav.stack.Layout = layout.NewStackLayout()
	nav.stack.Objects = objs
	nav.titles = titles
Repository: fyne-io/fyne
File: data/binding/preference.go (Go)

Code before:
	boundList[T]
	key string

	get       func(string) []T
	set       func(string, []T)
	setLookup preferenceLookupSetter[[]T]
}

func (b *prefBoundList[T]) checkForChange() {
	val := *b.val
	updated := b.get(b.key)
	if val == nil || len(updated) != len(val) {
		b.Set(updated)
		return
	}
	if val == nil {
		return
	}

	// incoming changes to a preference list are not at the child level
	for i, v := range val {
		if i >= len(updated) {
			break
		}

		if !b.comparator(v, updated[i]) {
			_ = b.items[i].(Item[T]).Set(updated[i])
		}
	}
}

func (b *prefBoundList[T]) replaceProvider(p fyne.Preferences) {
	b.get, b.set = b.setLookup(p)
}

type internalPrefs = interface{ WriteValues(func(map[string]any)) }

func bindPreferenceListComparable[T bool | float64 | int | string](key string, p fyne.Preferences,
	setLookup preferenceLookupSetter[[]T], compare func(T, T) bool) *prefBoundList[T] {
	if found, ok := lookupExistingListBinding[T](key, p); ok {
		return found
	}

	listen := &prefBoundList[T]{key: key, setLookup: setLookup}
	listen.replaceProvider(p)

	items := listen.get(listen.key)
	listen.boundList = *bindList(nil, compare)

	listen.boundList.AddListener(NewDataListener(func() {
		cached := *listen.val

Review comment (suggestion):
If we are to be consistent with the other functions here, the one called "comparable" should just pass a hard-coded `func(T, T) bool` into the function without the "comparable" suffix. Doing the same here would avoid the code duplication of all the comparison functions you have above.

Code after:
		b.Set(updated)
		return
	}
	if val == nil {
		return
	}

	// incoming changes to a preference list are not at the child level
	for i, v := range val {
		if i >= len(updated) {
			break
		}

		if !b.comparator(v, updated[i]) {
			_ = b.items[i].(Item[T]).Set(updated[i])
		}
	}
}

func (b *prefBoundList[T]) replaceProvider(p fyne.Preferences) {
	b.get, b.set = b.setLookup(p)
}

type internalPrefs = interface{ WriteValues(func(map[string]any)) }

func bindPreferenceListComparable[T bool | float64 | int | string](key string, p fyne.Preferences,
	setLookup preferenceLookupSetter[[]T]) *prefBoundList[T] {
	if found, ok := lookupExistingListBinding[T](key, p); ok {
		return found
	}

	listen := &prefBoundList[T]{key: key, setLookup: setLookup}
	listen.replaceProvider(p)

	items := listen.get(listen.key)
	listen.boundList = *bindList(nil, func(t1, t2 T) bool { return t1 == t2 })

	listen.boundList.AddListener(NewDataListener(func() {
		cached := *listen.val
		replaced := listen.get(listen.key)
		if len(cached) == len(replaced) {
			return
		}

		listen.set(listen.key, *listen.val)
		listen.trigger()
	}))

	listen.boundList.parentListener = func(index int) {
		listen.set(listen.key, *listen.val)
Repository: fyne-io/fyne
File: widget/locale.go (Go)

Code before:
package widget

import (
	"strings"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/lang"
)

const (
	localeDateFormatKey = "locale.date.format"
	localeWeekStartKey  = "locale.date.startweek"
)

var localeSettings = map[string]map[string]string{
	"": {
		localeDateFormatKey: "02/01/2006",
		localeWeekStartKey:  "Monday",
	},
	"BR": {
		localeDateFormatKey: "02/01/2006",
		localeWeekStartKey:  "Sunday",
	},
	"BZ": {
		localeDateFormatKey: "02/01/2006",
		localeWeekStartKey:  "Sunday",
	},
	"CA": {
		localeDateFormatKey: "02/01/2006",
		localeWeekStartKey:  "Sunday",
	},
	"CO": {
		localeDateFormatKey: "02/01/2006",
		localeWeekStartKey:  "Sunday",
	},
	"DO": {
		localeDateFormatKey: "02/01/2006",
		localeWeekStartKey:  "Sunday",
	},
	"GT": {

Review comment (performance):
This seems like a very memory inefficient data structure with quite a lot of duplicated data. Is there any way we can make this more efficient as languages grow?

One idea I have is to just use trucks and avoid the map inside map. It might also make sense to have the starting day as an index (maya be as an enum) and not a string to avoid duplicating that data a lot. 

Code after:
package widget

import (
	"strings"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/lang"
)

type weekday int

const (
	monday weekday = iota // default
	sunday
	saturday
)

func (w weekday) String() string {
	switch w {
	case sunday:
		return "Sunday"
	case saturday:
		return "Saturday"
	default:
		return "Monday"
	}
}

type localeSetting struct {
	dateFormat   string
	weekStartDay weekday
}

const defaultDateFormat = "02/01/2006"

var localeSettings = map[string]localeSetting{
	"": {
		dateFormat:   defaultDateFormat,
		weekStartDay: monday,
	},
Repository: fyne-io/fyne
File: layout/rowwrap.go (Go)

Code before:
package layout

import (
	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/theme"
)

type rowWrapLayout struct {
	rowCount          int
	horizontalPadding float32
	verticalPadding   float32
}

// NewRowWrapLayout returns a layout that dynamically arranges objects
// with the same height in rows and wraps them as necessary.
//
// Object visibility is supported.
//
// Since: 2.7
func NewRowWrapLayout() fyne.Layout {
	return &rowWrapLayout{
		horizontalPadding: theme.Padding(),
		verticalPadding:   theme.Padding(),
	}
}

// NewRowWrapLayoutWithCustomPadding creates a new RowWrapLayout instance
// with the specified paddings.
//
// Since: 2.7
func NewRowWrapLayoutWithCustomPadding(horizontal, vertical float32) fyne.Layout {
	return &rowWrapLayout{
		horizontalPadding: horizontal,
		verticalPadding:   vertical,
	}
}

var _ fyne.Layout = (*rowWrapLayout)(nil)

// MinSize finds the smallest size that satisfies all the child objects.
// For a RowWrapLayout this is the width of the widest child
// and the height of the first child multiplied by the number of children,
// with appropriate padding between them.
func (l *rowWrapLayout) MinSize(objects []fyne.CanvasObject) fyne.Size {
	if len(objects) == 0 {
		return fyne.NewSize(0, 0)
	}
	rows := l.rowCount
	if rows == 0 {

Review comment (suggestion):
Fewer theme lookups is usually better:
```suggestion
	padding := theme.Padding()
	return &rowWrapLayout{
		horizontalPadding: padding,
		verticalPadding:   padding,
	}
```

Code after:
package layout

import (
	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/theme"
)

type rowWrapLayout struct {
	horizontalPadding float32
	minSize           fyne.Size
	verticalPadding   float32
}

// NewRowWrapLayout returns a layout that dynamically arranges objects of similar height
// in rows and wraps them dynamically.
// Objects are separated with horizontal and vertical padding.
//
// Since: 2.7
func NewRowWrapLayout() fyne.Layout {
	p := theme.Padding()
	return &rowWrapLayout{
		horizontalPadding: p,
		verticalPadding:   p,
	}
}

// NewRowWrapLayoutWithCustomPadding returns a new RowWrapLayout instance
// with custom horizontal and inner padding.
//
// Since: 2.7
func NewRowWrapLayoutWithCustomPadding(horizontal, vertical float32) fyne.Layout {
	return &rowWrapLayout{
		horizontalPadding: horizontal,
		verticalPadding:   vertical,
	}
}

var _ fyne.Layout = (*rowWrapLayout)(nil)

// MinSize finds the smallest size that satisfies all the child objects.
// For a RowWrapLayout this is initially the width of the widest child
// and the height of the tallest child multiplied by the number of children,
// with appropriate padding between them.
// After Layout() has run it returns the actual min size.
func (l *rowWrapLayout) MinSize(objects []fyne.CanvasObject) fyne.Size {
	if len(objects) == 0 {
		return fyne.NewSize(0, 0)
	}
	if !l.minSize.IsZero() {
Repository: fyne-io/fyne
File: layout/rowwrap.go (Go)

Code before:
}

var _ fyne.Layout = (*rowWrapLayout)(nil)

// MinSize finds the smallest size that satisfies all the child objects.
// For a RowWrapLayout this is the width of the widest child
// and the height of the first child multiplied by the number of children,
// with appropriate padding between them.
func (l *rowWrapLayout) MinSize(objects []fyne.CanvasObject) fyne.Size {
	if len(objects) == 0 {
		return fyne.NewSize(0, 0)
	}
	rows := l.rowCount
	if rows == 0 {
		rows = 1
	}
	rowHeight := objects[0].MinSize().Height
	var width float32
	for _, o := range objects {
		size := o.MinSize()
		if size.Width > width {
			width = size.Width
		}
	}
	s := fyne.NewSize(width, rowHeight*float32(rows)+l.verticalPadding*float32(rows-1))
	return s
}

// Layout is called to pack all child objects into a specified size.
// For RowWrapLayout this will arrange all objects into rows of equal size.
func (l *rowWrapLayout) Layout(objects []fyne.CanvasObject, containerSize fyne.Size) {
	if len(objects) == 0 {
		return
	}
	rowHeight := objects[0].MinSize().Height
	pos := fyne.NewPos(0, 0)
	rows := 1
	for _, o := range objects {
		if !o.Visible() {
			continue
		}
		size := o.MinSize()
		o.Resize(size)
		w := size.Width + l.horizontalPadding
		if pos.X+w > containerSize.Width {
			pos = fyne.NewPos(0, float32(rows)*(rowHeight+l.verticalPadding))
			rows++
		}
		o.Move(pos)
		pos = pos.Add(fyne.NewPos(w, 0))
	}

Review comment (suggestion):
Cleaner to just return directly:
```suggestion
	return fyne.NewSize(width, rowHeight*float32(rows)+l.verticalPadding*float32(rows-1))
```

Code after:
}

var _ fyne.Layout = (*rowWrapLayout)(nil)

// MinSize finds the smallest size that satisfies all the child objects.
// For a RowWrapLayout this is initially the width of the widest child
// and the height of the tallest child multiplied by the number of children,
// with appropriate padding between them.
// After Layout() has run it returns the actual min size.
func (l *rowWrapLayout) MinSize(objects []fyne.CanvasObject) fyne.Size {
	if len(objects) == 0 {
		return fyne.NewSize(0, 0)
	}
	if !l.minSize.IsZero() {
		return l.minSize
	}
	var maxW, maxH float32
	var objCount int
	for _, o := range objects {
		if !o.Visible() {
			continue
		}
		objCount++
		s := o.MinSize()
		maxW = fyne.Max(maxW, s.Width)
		maxH = fyne.Max(maxH, s.Height)
	}
	return fyne.NewSize(maxW, l.minHeight(maxH, objCount))
}

func (l *rowWrapLayout) minHeight(rowHeight float32, rowCount int) float32 {
	return rowHeight*float32(rowCount) + l.verticalPadding*float32(rowCount-1)
}

// Layout is called to pack all child objects into a specified size.
// For RowWrapLayout this will arrange all objects into rows of equal size
// and wrap objects into additional rows as needed.
func (l *rowWrapLayout) Layout(objects []fyne.CanvasObject, containerSize fyne.Size) {
	if len(objects) == 0 {
		return
	}
	var maxH float32
	for _, o := range objects {
		if !o.Visible() {
			continue
		}
		maxH = fyne.Max(maxH, o.MinSize().Height)
	}
	var minSize fyne.Size
	pos := fyne.NewPos(0, 0)
	rows := 1
Repository: fyne-io/fyne
File: layout/rowwrap.go (Go)

Code before:
// with appropriate padding between them.
// After Layout() has run it returns the actual min size.
func (l *rowWrapLayout) MinSize(objects []fyne.CanvasObject) fyne.Size {
	if len(objects) == 0 {
		return fyne.NewSize(0, 0)
	}
	if !l.minSize.IsZero() {
		return l.minSize
	}
	var maxW, maxH float32
	var objCount int
	for _, o := range objects {
		if !o.Visible() {
			continue
		}
		objCount++
		s := o.MinSize()
		maxW = fyne.Max(maxW, s.Width)
		maxH = fyne.Max(maxH, s.Height)
	}
	return fyne.NewSize(maxW, l.minHeight(maxH, objCount))
}

func (l *rowWrapLayout) minHeight(rowHeight float32, rowCount int) float32 {
	height := rowHeight*float32(rowCount) + l.verticalPadding*float32(rowCount-1)
	return height
}

// Layout is called to pack all child objects into a specified size.
// For RowWrapLayout this will arrange all objects into rows of equal size
// and wrap objects into additional rows as needed.
func (l *rowWrapLayout) Layout(objects []fyne.CanvasObject, containerSize fyne.Size) {
	if len(objects) == 0 {
		return
	}
	var maxH float32
	for _, o := range objects {
		if !o.Visible() {
			continue
		}
		maxH = fyne.Max(maxH, o.MinSize().Height)
	}
	var minSize fyne.Size
	pos := fyne.NewPos(0, 0)
	rows := 1
	isFirst := true
	for _, o := range objects {
		if !o.Visible() {
			continue
		}
		size := o.MinSize()

Review comment (suggestion):
```suggestion
	return rowHeight*float32(rowCount) + l.verticalPadding*float32(rowCount-1)
```

Code after:
// with appropriate padding between them.
// After Layout() has run it returns the actual min size.
func (l *rowWrapLayout) MinSize(objects []fyne.CanvasObject) fyne.Size {
	if len(objects) == 0 {
		return fyne.NewSize(0, 0)
	}
	if !l.minSize.IsZero() {
		return l.minSize
	}
	var maxW, maxH float32
	var objCount int
	for _, o := range objects {
		if !o.Visible() {
			continue
		}
		objCount++
		s := o.MinSize()
		maxW = fyne.Max(maxW, s.Width)
		maxH = fyne.Max(maxH, s.Height)
	}
	return fyne.NewSize(maxW, l.minHeight(maxH, objCount))
}

func (l *rowWrapLayout) minHeight(rowHeight float32, rowCount int) float32 {
	return rowHeight*float32(rowCount) + l.verticalPadding*float32(rowCount-1)
}

// Layout is called to pack all child objects into a specified size.
// For RowWrapLayout this will arrange all objects into rows of equal size
// and wrap objects into additional rows as needed.
func (l *rowWrapLayout) Layout(objects []fyne.CanvasObject, containerSize fyne.Size) {
	if len(objects) == 0 {
		return
	}
	var maxH float32
	for _, o := range objects {
		if !o.Visible() {
			continue
		}
		maxH = fyne.Max(maxH, o.MinSize().Height)
	}
	var minSize fyne.Size
	pos := fyne.NewPos(0, 0)
	rows := 1
	isFirst := true
	for _, o := range objects {
		if !o.Visible() {
			continue
		}
		size := o.MinSize()
		o.Resize(size)
Repository: fyne-io/fyne
File: internal/driver/glfw/loop.go (Go)

Code before:
				}
			}

			d.animation.TickAnimations()
			d.drawSingleFrame()
		}
	}
}

func (d *gLDriver) destroyWindow(w *window, index int) {
	w.visible = false
	w.viewport.Destroy()
	w.destroy(d)

	if index < len(d.windows)-1 {
		copy(d.windows[index:], d.windows[index+1:])
	}
	d.windows[len(d.windows)-1] = nil
	d.windows = d.windows[:len(d.windows)-1]

	if len(d.windows) == 0 {
		d.Quit()
	}
}

func (d *gLDriver) repaintWindow(w *window) bool {
	canvas := w.canvas
	freed := false
	if canvas.EnsureMinSize() {
		w.shouldExpand = true
	}
	freed = canvas.FreeDirtyTextures() > 0

	updateGLContext(w)
	canvas.paint(canvas.Size())

	view := w.viewport
	visible := w.visible

	if view != nil && visible {
		view.SwapBuffers()
	}

	// mark that we have walked the window and don't
	// need to walk it again to mark caches alive
	w.lastWalkedTime = time.Now()
	w.lastWalkedTime = time.Now()
	return freed
}

// refreshWindow requests that the specified window be redrawn

Review comment (suggestion):
It seems like the contract for this function changed so that the caller is now responsible for calling it with GL context? I think there may be one call path where this isn't the case (window.Resize -> platformResize)

Code after:
				}
			}

			d.animation.TickAnimations()
			d.drawSingleFrame()
		}
	}
}

func (d *gLDriver) destroyWindow(w *window, index int) {
	w.visible = false
	w.viewport.Destroy()
	w.destroy(d)

	if index < len(d.windows)-1 {
		copy(d.windows[index:], d.windows[index+1:])
	}
	d.windows[len(d.windows)-1] = nil
	d.windows = d.windows[:len(d.windows)-1]

	if len(d.windows) == 0 {
		d.Quit()
	}
}

func (d *gLDriver) repaintWindow(w *window) bool {
	canvas := w.canvas
	freed := false
	if canvas.EnsureMinSize() {
		w.shouldExpand = true
	}
	freed = canvas.FreeDirtyTextures() > 0

	updateGLContext(w)
	canvas.paint(canvas.Size())

	view := w.viewport
	visible := w.visible

	if view != nil && visible {
		view.SwapBuffers()
	}

	// mark that we have walked the window and don't
	// need to walk it again to mark caches alive
	w.lastWalkedTime = time.Now()
	return freed
}

// refreshWindow requests that the specified window be redrawn
func refreshWindow(w *window) {
Repository: fyne-io/fyne
File: storage/uri.go (Go)

Code before:
//   - If the scheme of the given URI does not have a registered
//     WritableRepository instance, then this method will fail with a
//     repository.ErrOperationNotSupported.
//
// Delete is backed by the repository system - this function calls
// into a scheme-specific implementation from a registered repository.
//
// Since: 2.0
func Delete(u fyne.URI) error {
	repo, err := repository.ForURI(u)
	if err != nil {
		return err
	}

	wrepo, ok := repo.(repository.WritableRepository)
	if !ok {
		return repository.ErrOperationNotSupported
	}

	return wrepo.Delete(u)

}

func DeleteRecursive(u fyne.URI) error {
	list, err := List(u)

	if err != nil {
		return err
	}

	for _, v := range list {
		listable, err := CanList(v)
		if err != nil {
			return err
		}
		if !listable {
			err = Delete(v)
			if err != nil {
				return err
			}
			continue
		} else {
			err = DeleteRecursive(v)

			if err != nil {
				return err
			}
		}
	}

	err = Delete(u)

Review comment (suggestion):
Please remove lines like this between the function call and checking errors. This isn't idiomatic Go code. Same applies in more places.

Code after:
func Delete(u fyne.URI) error {
	repo, err := repository.ForURI(u)
	if err != nil {
		return err
	}

	wrepo, ok := repo.(repository.WritableRepository)
	if !ok {
		return repository.ErrOperationNotSupported
	}

	return wrepo.Delete(u)
}

// DeleteAll destroys, deletes, or otherwise removes the resource referenced
// by the URI and any child resources for listable URIs.
//
// DeleteAll is backed by the repository system - this function calls
// into a scheme-specific implementation from a registered repository.
//
// Since: 2.7
func DeleteAll(u fyne.URI) error {
	repo, err := repository.ForURI(u)
	if err != nil {
		return err
	}

	drepo, ok := repo.(repository.DeleteAllRepository)
	if !ok {
		return repository.GenericDeleteAll(u)
	}

	return drepo.DeleteAll(u)
}

// Reader returns URIReadCloser set up to read from the resource that the
// URI references.
//
// This method can fail in several ways:
//
//   - Different permissions or credentials are required to read the
//     referenced resource.
//
//   - This URI scheme could represent some resources that can be read,
//     but this particular URI references a resources that is not
//     something that can be read.
//
//   - Attempting to set up the reader depended on a lower level
//     operation such as a network or filesystem access that has failed
//     in some way.
//
Repository: fyne-io/fyne
File: storage/uri.go (Go)

Code before:

func DeleteRecursive(u fyne.URI) error {
	list, err := List(u)

	if err != nil {
		return err
	}

	for _, v := range list {
		listable, err := CanList(v)
		if err != nil {
			return err
		}
		if !listable {
			err = Delete(v)
			if err != nil {
				return err
			}
			continue
		} else {
			err = DeleteRecursive(v)

			if err != nil {
				return err
			}
		}
	}

	err = Delete(u)

	if err != nil {
		return err
	}

	return nil
}

// Reader returns URIReadCloser set up to read from the resource that the
// URI references.
//
// This method can fail in several ways:
//
//   - Different permissions or credentials are required to read the
//     referenced resource.
//
//   - This URI scheme could represent some resources that can be read,
//     but this particular URI references a resources that is not
//     something that can be read.
//
//   - Attempting to set up the reader depended on a lower level
//     operation such as a network or filesystem access that has failed

Review comment (suggestion):
You can remove the else statement due to the continue call.
```suggestion
			continue
		}

		err = DeleteRecursive(v)
		if err != nil {
			return err
		}
```


Code after:
	repo, err := repository.ForURI(u)
	if err != nil {
		return err
	}

	drepo, ok := repo.(repository.DeleteAllRepository)
	if !ok {
		return repository.GenericDeleteAll(u)
	}

	return drepo.DeleteAll(u)
}

// Reader returns URIReadCloser set up to read from the resource that the
// URI references.
//
// This method can fail in several ways:
//
//   - Different permissions or credentials are required to read the
//     referenced resource.
//
//   - This URI scheme could represent some resources that can be read,
//     but this particular URI references a resources that is not
//     something that can be read.
//
//   - Attempting to set up the reader depended on a lower level
//     operation such as a network or filesystem access that has failed
//     in some way.
//
// Reader is backed by the repository system - this function calls
// into a scheme-specific implementation from a registered repository.
//
// Since: 2.0
func Reader(u fyne.URI) (fyne.URIReadCloser, error) {
	repo, err := repository.ForURI(u)
	if err != nil {
		return nil, err
	}

	return repo.Reader(u)
}

// CanRead determines if a given URI could be written to using the Reader()
// method. It is preferred to check if a URI is readable using this method
// before calling Reader(), because the underlying operations required to
// attempt to read and then report an error may be slower than the operations
// needed to test if a URI is readable. Keep in mind however that even if
// CanRead returns true, you must still do appropriate error handling for
// Reader(), as the underlying filesystem may have changed since you called
// CanRead.
//