summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2023-01-01 17:49:11 -0700
committerLuke Shumaker <lukeshu@lukeshu.com>2023-01-01 22:42:08 -0700
commit493ec396fab32d9e8859e34ad497fdb0a910a33c (patch)
treee174a7676cbe222b343004336b53e37cd37101a7 /lib
parent95c8965e8b897aa69a3fbdea42c79513f55457ad (diff)
lint: Turn on forcetypeassert
Diffstat (limited to 'lib')
-rw-r--r--lib/binstruct/size.go3
-rw-r--r--lib/btrfs/btrfsitem/items.go3
-rw-r--r--lib/btrfs/io2_lv.go18
-rw-r--r--lib/btrfs/io4_fs.go129
-rw-r--r--lib/containers/lru.go5
-rw-r--r--lib/containers/set.go7
-rw-r--r--lib/containers/syncmap.go6
-rw-r--r--lib/textui/progress.go1
8 files changed, 116 insertions, 56 deletions
diff --git a/lib/binstruct/size.go b/lib/binstruct/size.go
index 365da85..52fa380 100644
--- a/lib/binstruct/size.go
+++ b/lib/binstruct/size.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -30,6 +30,7 @@ var (
func staticSize(typ reflect.Type) (int, error) {
if typ.Implements(staticSizerType) {
+ //nolint:forcetypeassert // Already did a type check via reflection.
return reflect.New(typ).Elem().Interface().(StaticSizer).BinaryStaticSize(), nil
}
if typ.Implements(marshalerType) || typ.Implements(unmarshalerType) {
diff --git a/lib/btrfs/btrfsitem/items.go b/lib/btrfs/btrfsitem/items.go
index 29b3cb0..d300179 100644
--- a/lib/btrfs/btrfsitem/items.go
+++ b/lib/btrfs/btrfsitem/items.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -79,5 +79,6 @@ func UnmarshalItem(key btrfsprim.Key, csumType btrfssum.CSumType, dat []byte) It
key.ItemType, len(dat), n),
}
}
+ //nolint:forcetypeassert // items_gen.go has all types in keytype2gotype implement the Item interface.
return retPtr.Elem().Interface().(Item)
}
diff --git a/lib/btrfs/io2_lv.go b/lib/btrfs/io2_lv.go
index 5580285..3f82cd0 100644
--- a/lib/btrfs/io2_lv.go
+++ b/lib/btrfs/io2_lv.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -171,10 +171,20 @@ func (fs *FS) initDev(ctx context.Context, sb btrfstree.Superblock) error {
if item.Key.ItemType != btrfsitem.CHUNK_ITEM_KEY {
return nil
}
- for _, mapping := range item.Body.(btrfsitem.Chunk).Mappings(item.Key) {
- if err := fs.LV.AddMapping(mapping); err != nil {
- return err
+ switch itemBody := item.Body.(type) {
+ case btrfsitem.Chunk:
+ for _, mapping := range itemBody.Mappings(item.Key) {
+ if err := fs.LV.AddMapping(mapping); err != nil {
+ return err
+ }
}
+ case btrfsitem.Error:
+ // do nothing
+ default:
+ // This is a panic because the item decoder should not emit CHUNK_ITEM items as
+ // anything but btrfsitem.Chunk or btrfsitem.Error without this code also being
+ // updated.
+ panic(fmt.Errorf("should not happen: CHUNK_ITEM has unexpected item type: %T", itemBody))
}
return nil
},
diff --git a/lib/btrfs/io4_fs.go b/lib/btrfs/io4_fs.go
index ea81bc2..d7c2770 100644
--- a/lib/btrfs/io4_fs.go
+++ b/lib/btrfs/io4_fs.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -152,17 +152,29 @@ func (sv *Subvolume) LoadFullInode(inode btrfsprim.ObjID) (*FullInode, error) {
for _, item := range items {
switch item.Key.ItemType {
case btrfsitem.INODE_ITEM_KEY:
- itemBody := item.Body.(btrfsitem.Inode)
- if val.InodeItem != nil {
- if !reflect.DeepEqual(itemBody, *val.InodeItem) {
- val.Errs = append(val.Errs, fmt.Errorf("multiple inodes"))
+ switch itemBody := item.Body.(type) {
+ case btrfsitem.Inode:
+ if val.InodeItem != nil {
+ if !reflect.DeepEqual(itemBody, *val.InodeItem) {
+ val.Errs = append(val.Errs, fmt.Errorf("multiple inodes"))
+ }
+ continue
}
- continue
+ val.InodeItem = &itemBody
+ case btrfsitem.Error:
+ val.Errs = append(val.Errs, fmt.Errorf("malformed INODE_ITEM: %w", itemBody.Err))
+ default:
+ panic(fmt.Errorf("should not happen: INODE_ITEM has unexpected item type: %T", itemBody))
}
- val.InodeItem = &itemBody
case btrfsitem.XATTR_ITEM_KEY:
- itemBody := item.Body.(btrfsitem.DirEntry)
- val.XAttrs[string(itemBody.Name)] = string(itemBody.Data)
+ switch itemBody := item.Body.(type) {
+ case btrfsitem.DirEntry:
+ val.XAttrs[string(itemBody.Name)] = string(itemBody.Data)
+ case btrfsitem.Error:
+ val.Errs = append(val.Errs, fmt.Errorf("malformed XATTR_ITEM: %w", itemBody.Err))
+ default:
+ panic(fmt.Errorf("should not happen: XATTR_ITEM has unexpected item type: %T", itemBody))
+ }
default:
val.OtherItems = append(val.OtherItems, item)
}
@@ -200,48 +212,66 @@ func (ret *Dir) populate() {
for _, item := range ret.OtherItems {
switch item.Key.ItemType {
case btrfsitem.INODE_REF_KEY:
- body := item.Body.(btrfsitem.InodeRefs)
- if len(body) != 1 {
- ret.Errs = append(ret.Errs, fmt.Errorf("INODE_REF item with %d entries on a directory",
- len(body)))
- continue
- }
- ref := InodeRef{
- Inode: btrfsprim.ObjID(item.Key.Offset),
- InodeRef: body[0],
- }
- if ret.DotDot != nil {
- if !reflect.DeepEqual(ref, *ret.DotDot) {
- ret.Errs = append(ret.Errs, fmt.Errorf("multiple INODE_REF items on a directory"))
+ switch body := item.Body.(type) {
+ case btrfsitem.InodeRefs:
+ if len(body) != 1 {
+ ret.Errs = append(ret.Errs, fmt.Errorf("INODE_REF item with %d entries on a directory",
+ len(body)))
+ continue
+ }
+ ref := InodeRef{
+ Inode: btrfsprim.ObjID(item.Key.Offset),
+ InodeRef: body[0],
}
- continue
+ if ret.DotDot != nil {
+ if !reflect.DeepEqual(ref, *ret.DotDot) {
+ ret.Errs = append(ret.Errs, fmt.Errorf("multiple INODE_REF items on a directory"))
+ }
+ continue
+ }
+ ret.DotDot = &ref
+ case btrfsitem.Error:
+ ret.Errs = append(ret.Errs, fmt.Errorf("malformed INODE_REF: %w", body.Err))
+ default:
+ panic(fmt.Errorf("should not happen: INODE_REF has unexpected item type: %T", body))
}
- ret.DotDot = &ref
case btrfsitem.DIR_ITEM_KEY:
- entry := item.Body.(btrfsitem.DirEntry)
- namehash := btrfsitem.NameHash(entry.Name)
- if namehash != item.Key.Offset {
- ret.Errs = append(ret.Errs, fmt.Errorf("direntry crc32c mismatch: key=%#x crc32c(%q)=%#x",
- item.Key.Offset, entry.Name, namehash))
- continue
- }
- if other, exists := ret.ChildrenByName[string(entry.Name)]; exists {
- if !reflect.DeepEqual(entry, other) {
- ret.Errs = append(ret.Errs, fmt.Errorf("multiple instances of direntry name %q", entry.Name))
+ switch entry := item.Body.(type) {
+ case btrfsitem.DirEntry:
+ namehash := btrfsitem.NameHash(entry.Name)
+ if namehash != item.Key.Offset {
+ ret.Errs = append(ret.Errs, fmt.Errorf("direntry crc32c mismatch: key=%#x crc32c(%q)=%#x",
+ item.Key.Offset, entry.Name, namehash))
+ continue
+ }
+ if other, exists := ret.ChildrenByName[string(entry.Name)]; exists {
+ if !reflect.DeepEqual(entry, other) {
+ ret.Errs = append(ret.Errs, fmt.Errorf("multiple instances of direntry name %q", entry.Name))
+ }
+ continue
}
- continue
+ ret.ChildrenByName[string(entry.Name)] = entry
+ case btrfsitem.Error:
+ ret.Errs = append(ret.Errs, fmt.Errorf("malformed DIR_ITEM: %w", entry.Err))
+ default:
+ panic(fmt.Errorf("should not happen: DIR_ITEM has unexpected item type: %T", entry))
}
- ret.ChildrenByName[string(entry.Name)] = entry
case btrfsitem.DIR_INDEX_KEY:
index := item.Key.Offset
- entry := item.Body.(btrfsitem.DirEntry)
- if other, exists := ret.ChildrenByIndex[index]; exists {
- if !reflect.DeepEqual(entry, other) {
- ret.Errs = append(ret.Errs, fmt.Errorf("multiple instances of direntry index %v", index))
+ switch entry := item.Body.(type) {
+ case btrfsitem.DirEntry:
+ if other, exists := ret.ChildrenByIndex[index]; exists {
+ if !reflect.DeepEqual(entry, other) {
+ ret.Errs = append(ret.Errs, fmt.Errorf("multiple instances of direntry index %v", index))
+ }
+ continue
}
- continue
+ ret.ChildrenByIndex[index] = entry
+ case btrfsitem.Error:
+ ret.Errs = append(ret.Errs, fmt.Errorf("malformed DIR_INDEX: %w", entry.Err))
+ default:
+ panic(fmt.Errorf("should not happen: DIR_INDEX has unexpected item type: %T", entry))
}
- ret.ChildrenByIndex[index] = entry
default:
panic(fmt.Errorf("TODO: handle item type %v", item.Key.ItemType))
}
@@ -317,10 +347,17 @@ func (ret *File) populate() {
case btrfsitem.INODE_REF_KEY:
// TODO
case btrfsitem.EXTENT_DATA_KEY:
- ret.Extents = append(ret.Extents, FileExtent{
- OffsetWithinFile: int64(item.Key.Offset),
- FileExtent: item.Body.(btrfsitem.FileExtent),
- })
+ switch itemBody := item.Body.(type) {
+ case btrfsitem.FileExtent:
+ ret.Extents = append(ret.Extents, FileExtent{
+ OffsetWithinFile: int64(item.Key.Offset),
+ FileExtent: itemBody,
+ })
+ case btrfsitem.Error:
+ ret.Errs = append(ret.Errs, fmt.Errorf("malformed EXTENT_DATA: %w", itemBody.Err))
+ default:
+ panic(fmt.Errorf("should not happen: EXTENT_DATA has unexpected item type: %T", itemBody))
+ }
default:
panic(fmt.Errorf("TODO: handle item type %v", item.Key.ItemType))
}
diff --git a/lib/containers/lru.go b/lib/containers/lru.go
index a235a12..12446b0 100644
--- a/lib/containers/lru.go
+++ b/lib/containers/lru.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -44,6 +44,7 @@ func (c *LRUCache[K, V]) Get(key K) (value V, ok bool) {
c.init()
_value, ok := c.inner.Get(key)
if ok {
+ //nolint:forcetypeassert // Typed wrapper around untyped lib.
value = _value.(V)
}
return value, ok
@@ -53,6 +54,7 @@ func (c *LRUCache[K, V]) Keys() []K {
untyped := c.inner.Keys()
typed := make([]K, len(untyped))
for i := range untyped {
+ //nolint:forcetypeassert // Typed wrapper around untyped lib.
typed[i] = untyped[i].(K)
}
return typed
@@ -65,6 +67,7 @@ func (c *LRUCache[K, V]) Peek(key K) (value V, ok bool) {
c.init()
_value, ok := c.inner.Peek(key)
if ok {
+ //nolint:forcetypeassert // Typed wrapper around untyped lib.
value = _value.(V)
}
return value, ok
diff --git a/lib/containers/set.go b/lib/containers/set.go
index 67ba7ac..4fc8aad 100644
--- a/lib/containers/set.go
+++ b/lib/containers/set.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -22,7 +22,10 @@ var (
_ lowmemjson.Decodable = (*Set[int])(nil)
)
-func cast[T any](x any) T { return x.(T) }
+func cast[T any](x any) T {
+ //nolint:forcetypeassert // Only called within a type switch.
+ return x.(T)
+}
func (o Set[T]) EncodeJSON(w io.Writer) error {
var less func(a, b T) bool
diff --git a/lib/containers/syncmap.go b/lib/containers/syncmap.go
index fb7f59b..4af678f 100644
--- a/lib/containers/syncmap.go
+++ b/lib/containers/syncmap.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -18,6 +18,7 @@ func (m *SyncMap[K, V]) Delete(key K) {
func (m *SyncMap[K, V]) Load(key K) (value V, ok bool) {
_value, ok := m.inner.Load(key)
if ok {
+ //nolint:forcetypeassert // Typed wrapper around untyped lib.
value = _value.(V)
}
return value, ok
@@ -25,17 +26,20 @@ func (m *SyncMap[K, V]) Load(key K) (value V, ok bool) {
func (m *SyncMap[K, V]) LoadAndDelete(key K) (value V, loaded bool) {
_value, ok := m.inner.LoadAndDelete(key)
if ok {
+ //nolint:forcetypeassert // Typed wrapper around untyped lib.
value = _value.(V)
}
return value, ok
}
func (m *SyncMap[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) {
_actual, loaded := m.inner.LoadOrStore(key, value)
+ //nolint:forcetypeassert // Typed wrapper around untyped lib.
actual = _actual.(V)
return actual, loaded
}
func (m *SyncMap[K, V]) Range(f func(key K, value V) bool) {
m.inner.Range(func(key, value any) bool {
+ //nolint:forcetypeassert // Typed wrapper around untyped lib.
return f(key.(K), value.(V))
})
}
diff --git a/lib/textui/progress.go b/lib/textui/progress.go
index 56fda96..68d986f 100644
--- a/lib/textui/progress.go
+++ b/lib/textui/progress.go
@@ -56,6 +56,7 @@ func (p *Progress[T]) Done() {
}
func (p *Progress[T]) flush(force bool) {
+ //nolint:forcetypeassert // It wasn't worth it to me (yet?) to make a typed wrapper around atomic.Value.
cur := p.cur.Load().(T)
if !force && cur == p.oldStat {
return