1- use std:: collections:: { BTreeMap , BTreeSet } ;
1+ use std:: collections:: { BTreeMap , BTreeSet , HashMap } ;
22use std:: fmt;
33use std:: sync:: Arc ;
44#[ cfg( not( target_os = "wasi" ) ) ]
@@ -28,6 +28,10 @@ const LISTING_PAGE: usize = 200;
2828/// bounds the loop when the response lies; a partial or empty page also ends
2929/// paging early.
3030const MAX_LISTING_PAGES : usize = 25 ;
31+ /// Most server supplied listing rows skilld trusts per response, mirroring
32+ /// `MAX_LISTING_PAGES`: the curator collection list and each collection's
33+ /// entry list are capped here so a malformed response cannot fan out.
34+ const MAX_LISTING_ENTRIES : usize = MAX_LISTING_PAGES ;
3135const ARTIFACT_LIMIT : usize = 64 * 1024 * 1024 ;
3236const DIRECT_BLOB_LIMIT : usize = 12 * 1024 * 1024 ;
3337const MAX_REDIRECTS : usize = 3 ;
@@ -1611,18 +1615,26 @@ impl SkilldRemote {
16111615 self . service_json ( url)
16121616 }
16131617
1614- /// Every Skill one Repository carries, by name.
1618+ /// Every Skill one Repository carries, by name. The owner index fetch is
1619+ /// memoized per Repository in `memo` for one listing, so repeated
1620+ /// collection entries naming the same Repository cost one fetch.
16151621 fn repository_skills (
16161622 & self ,
16171623 owner : & str ,
16181624 repository : & str ,
1625+ memo : & mut HashMap < ( String , String ) , Vec < ListedSkill > > ,
16191626 ) -> Result < Vec < ListedSkill > , RemoteError > {
1627+ let key = ( owner. to_ascii_lowercase ( ) , repository. to_ascii_lowercase ( ) ) ;
1628+ if let Some ( items) = memo. get ( & key) {
1629+ return Ok ( items. clone ( ) ) ;
1630+ }
16201631 let mut items = self
16211632 . owner_skills ( owner) ?
16221633 . into_iter ( )
16231634 . filter ( |skill| skill. repository . eq_ignore_ascii_case ( repository) )
16241635 . collect :: < Vec < _ > > ( ) ;
16251636 items. sort_by ( |left, right| left. name . cmp ( & right. name ) ) ;
1637+ memo. insert ( key, items. clone ( ) ) ;
16261638 Ok ( items)
16271639 }
16281640
@@ -1653,6 +1665,7 @@ impl SkilldRemote {
16531665 name : row. name ,
16541666 reason : row. reason ,
16551667 } )
1668+ . take ( MAX_LISTING_ENTRIES )
16561669 . collect ( ) )
16571670 }
16581671
@@ -1676,6 +1689,7 @@ impl SkilldRemote {
16761689 fn expand_entries (
16771690 & self ,
16781691 entries : Vec < CollectionEntry > ,
1692+ memo : & mut HashMap < ( String , String ) , Vec < ListedSkill > > ,
16791693 ) -> Result < Vec < ListedSkill > , RemoteError > {
16801694 let mut seen = BTreeSet :: new ( ) ;
16811695 let mut items = Vec :: new ( ) ;
@@ -1686,7 +1700,7 @@ impl SkilldRemote {
16861700 . into_iter ( )
16871701 . collect ( )
16881702 }
1689- None => self . repository_skills ( & entry. owner , & entry. repository ) ?,
1703+ None => self . repository_skills ( & entry. owner , & entry. repository , memo ) ?,
16901704 } ;
16911705 for skill in expanded {
16921706 if seen. insert ( skill. selector ( ) ) {
@@ -1732,19 +1746,24 @@ fn not_found_as_source(error: RemoteError, message: String) -> RemoteError {
17321746
17331747impl RemoteProvider for SkilldRemote {
17341748 fn list_skills ( & self , reference : & MultiSkillRef ) -> Result < SkillListing , RemoteError > {
1749+ let mut memo = HashMap :: new ( ) ;
17351750 let items = match reference {
17361751 MultiSkillRef :: Repository { owner, repository } => {
1737- self . repository_skills ( owner, repository) ?
1752+ self . repository_skills ( owner, repository, & mut memo ) ?
17381753 }
17391754 MultiSkillRef :: Collection { login, slug } => {
1740- self . expand_entries ( self . collection_entries ( login, slug) ?) ?
1755+ self . expand_entries ( self . collection_entries ( login, slug) ?, & mut memo ) ?
17411756 }
17421757 MultiSkillRef :: Curator { login } => {
17431758 let mut entries = Vec :: new ( ) ;
1744- for slug in self . curator_slugs ( login) ? {
1759+ for slug in self
1760+ . curator_slugs ( login) ?
1761+ . into_iter ( )
1762+ . take ( MAX_LISTING_ENTRIES )
1763+ {
17451764 entries. extend ( self . collection_entries ( login, & slug) ?) ;
17461765 }
1747- self . expand_entries ( entries) ?
1766+ self . expand_entries ( entries, & mut memo ) ?
17481767 }
17491768 } ;
17501769 Ok ( SkillListing {
0 commit comments